@oneuptime/common 13.0.8 → 14.0.1

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 (514) hide show
  1. package/Models/AnalyticsModels/AuditLog.ts +23 -15
  2. package/Models/DatabaseModels/GlobalConfig.ts +24 -0
  3. package/Models/DatabaseModels/Index.ts +4 -0
  4. package/Models/DatabaseModels/Monitor.ts +3 -2
  5. package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
  6. package/Models/DatabaseModels/ServiceLevelObjectiveFeed.ts +2 -0
  7. package/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.ts +522 -0
  8. package/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.ts +38 -4
  9. package/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.ts +603 -0
  10. package/Scripts/generate-service-worker.js +65 -4
  11. package/Server/API/BaseAPI.ts +26 -5
  12. package/Server/API/GlobalConfigAPI.ts +228 -462
  13. package/Server/API/ProjectOIDC.ts +25 -16
  14. package/Server/API/ProjectSSO.ts +24 -16
  15. package/Server/API/StatusPageAPI.ts +100 -42
  16. package/Server/API/TeamMemberAPI.ts +10 -1
  17. package/Server/Enterprise/EnterpriseEdition.ts +649 -0
  18. package/Server/Enterprise/EnterpriseFeature.ts +48 -0
  19. package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +192 -0
  20. package/Server/Enterprise/EnterpriseServerModule.ts +233 -0
  21. package/Server/EnvironmentConfig.ts +147 -2
  22. package/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.ts +25 -0
  23. package/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.ts +248 -0
  24. package/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.ts +19 -0
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  26. package/Server/Middleware/UserAuthorization.ts +38 -16
  27. package/Server/Services/AuditLogService.ts +84 -1079
  28. package/Server/Services/DatabaseService.ts +10 -0
  29. package/Server/Services/EnterpriseLicenseService.ts +38 -0
  30. package/Server/Services/GlobalConfigService.ts +80 -1
  31. package/Server/Services/Index.ts +4 -0
  32. package/Server/Services/MonitorProbeService.ts +116 -20
  33. package/Server/Services/MonitorService.ts +59 -6
  34. package/Server/Services/MonitorStatusTimelineService.ts +284 -0
  35. package/Server/Services/MonitorTemplateService.ts +26 -0
  36. package/Server/Services/ProjectService.ts +284 -0
  37. package/Server/Services/RumSessionPinService.ts +25 -6
  38. package/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.ts +385 -0
  39. package/Server/Services/ServiceLevelObjectiveLabelRuleService.ts +51 -0
  40. package/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.ts +92 -16
  41. package/Server/Services/ServiceLevelObjectiveMonitorRuleService.ts +36 -1
  42. package/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.ts +521 -0
  43. package/Server/Services/ServiceLevelObjectiveOwnerRuleService.ts +51 -0
  44. package/Server/Services/ServiceLevelObjectiveService.ts +28 -0
  45. package/Server/Services/StatusPagePrivateUserService.ts +7 -3
  46. package/Server/Services/StatusPageService.ts +78 -1
  47. package/Server/Services/TeamMemberService.ts +11 -0
  48. package/Server/Services/TeamService.ts +10 -0
  49. package/Server/Services/UserService.ts +10 -17
  50. package/Server/Types/Database/Permissions/CreatePermission.ts +15 -0
  51. package/Server/Types/Database/Permissions/EditionPermission.ts +208 -18
  52. package/Server/Types/Database/Permissions/TablePermission.ts +10 -3
  53. package/Server/Types/Database/Permissions/UpdatePermission.ts +29 -0
  54. package/Server/Types/Markdown.ts +41 -0
  55. package/Server/Types/Workflow/Components/Telegram/SendMessageToChat.ts +27 -1
  56. package/Server/Utils/AI/Toolbox/SloTools.ts +1 -0
  57. package/Server/Utils/CommunityEditionSsoReport.ts +361 -0
  58. package/Server/Utils/EditionEnforcement.ts +233 -0
  59. package/Server/Utils/FrontendEnvironment.ts +41 -2
  60. package/Server/Utils/InstanceHealth/RedisHealth.ts +12 -277
  61. package/Server/Utils/Monitor/AffectedResourceList.ts +148 -0
  62. package/Server/Utils/Monitor/Criteria/CompareCriteria.ts +1 -1
  63. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
  64. package/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.ts +1 -1
  65. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +720 -465
  66. package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -0
  67. package/Server/Utils/Monitor/RootCauseList.ts +139 -0
  68. package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +28 -0
  69. package/Server/Utils/Slo/SloRulePatternValidator.ts +42 -0
  70. package/Server/Utils/Workspace/Slack/Slack.ts +423 -10
  71. package/Tests/App/Accounts/LoginPasskey.test.tsx +18 -0
  72. package/Tests/App/Accounts/LoginSsoEdition.test.tsx +616 -0
  73. package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +217 -0
  74. package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +357 -0
  75. package/Tests/App/AdminDashboard/EnterpriseLicensesShell.test.tsx +214 -0
  76. package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +271 -0
  77. package/Tests/App/AdminDashboard/HealthShells.test.tsx +659 -0
  78. package/Tests/App/Dashboard/AuditLogsAndComplianceShells.test.tsx +572 -0
  79. package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +547 -0
  80. package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +667 -0
  81. package/Tests/App/Dashboard/FeedFilterSortIntegration.test.tsx +1632 -0
  82. package/Tests/App/Dashboard/FeedOptionsLocales.test.ts +250 -0
  83. package/Tests/App/Dashboard/FeedOrdering.test.ts +279 -9
  84. package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +319 -0
  85. package/Tests/App/Dashboard/InvestigationFeedRefresh.test.tsx +60 -1
  86. package/Tests/App/Dashboard/InvestigationPanel.test.tsx +594 -3
  87. package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
  88. package/Tests/App/Dashboard/ProductOrientation.test.tsx +646 -0
  89. package/Tests/App/Dashboard/ResourceFeed.test.tsx +612 -2
  90. package/Tests/App/Dashboard/ResourceFeedPageWiring.test.ts +30 -0
  91. package/Tests/App/Dashboard/ResourceFeedPagesFilterSort.test.tsx +1202 -0
  92. package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +52 -1
  93. package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +45 -9
  94. package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +399 -0
  95. package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +214 -0
  96. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +1 -83
  97. package/Tests/App/Dashboard/SecurityEventsNavTabs.test.tsx +248 -0
  98. package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +1203 -0
  99. package/Tests/App/Dashboard/SloFeed.test.tsx +106 -1
  100. package/Tests/App/Dashboard/SloMonitorRuleCriteria.test.tsx +566 -0
  101. package/Tests/App/Dashboard/SloNavigationWiring.test.tsx +6 -4
  102. package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +186 -0
  103. package/Tests/App/Dashboard/SloOverviewKpiStrip.test.tsx +388 -44
  104. package/Tests/App/Dashboard/SloOverviewLayout.test.tsx +613 -0
  105. package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +11 -91
  106. package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +319 -0
  107. package/Tests/Helpers/RefreshAwareApiScan.ts +757 -0
  108. package/Tests/Helpers/TenantScopedRequestScan.ts +515 -0
  109. package/Tests/Models/DatabaseModels/ResourceFeedModels.test.ts +0 -8
  110. package/Tests/Models/DatabaseModels/SloLabelAndOwnerRuleModels.test.ts +404 -0
  111. package/Tests/Models/DatabaseModels/SloOverhaulModels.test.ts +17 -1
  112. package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
  113. package/Tests/Scripts/GenerateServiceWorker.test.ts +931 -0
  114. package/Tests/Server/API/BaseAPICreateItemDoesNotMutateModel.test.ts +130 -0
  115. package/Tests/Server/API/GlobalConfigLicense.test.ts +742 -497
  116. package/Tests/Server/API/OnCallReadinessAPI.test.ts +35 -909
  117. package/Tests/Server/API/SsoProviderListingsEdition.test.ts +432 -0
  118. package/Tests/Server/API/TeamMemberLeaveScimLockEdition.test.ts +252 -0
  119. package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +824 -0
  120. package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +643 -0
  121. package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +294 -0
  122. package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +93 -0
  123. package/Tests/Server/Enterprise/EnterpriseOnlyModulesLiveInEe.test.ts +582 -0
  124. package/Tests/Server/Enterprise/EnterpriseServerModule.test.ts +247 -0
  125. package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +502 -0
  126. package/Tests/Server/Enterprise/TestBillingFlag.ts +70 -0
  127. package/Tests/Server/EnvironmentConfigEnterpriseEdition.test.ts +314 -0
  128. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +289 -0
  129. package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +5 -1
  130. package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
  131. package/Tests/Server/Infrastructure/Postgres/AddSloLabelAndOwnerRulesMigration.test.ts +407 -0
  132. package/Tests/Server/Infrastructure/Postgres/AddSloMonitorRuleMonitorTypeMigration.test.ts +171 -0
  133. package/Tests/Server/Infrastructure/Postgres/SloProductOverhaulMigration.test.ts +88 -4
  134. package/Tests/Server/Middleware/UserAuthorization.test.ts +37 -2
  135. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +516 -0
  136. package/Tests/Server/Services/AuditLogService.test.ts +460 -990
  137. package/Tests/Server/Services/CreateAndReadResponsesKeepIds.test.ts +263 -0
  138. package/Tests/Server/Services/DatabaseServiceRuleCriteriaValidation.test.ts +104 -0
  139. package/Tests/Server/Services/EnterpriseLicenseServiceKeyGeneration.test.ts +151 -0
  140. package/Tests/Server/Services/GlobalConfigServiceLicenseColumns.test.ts +357 -0
  141. package/Tests/Server/Services/MonitorDestinationInfoIPv6.test.ts +101 -0
  142. package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +333 -0
  143. package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +303 -0
  144. package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +701 -0
  145. package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +31 -35
  146. package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +48 -1
  147. package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -0
  148. package/Tests/Server/Services/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
  149. package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleEngines.test.ts +1170 -0
  150. package/Tests/Server/Services/ServiceLevelObjectiveLabelAndOwnerRuleServices.test.ts +172 -0
  151. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.test.ts +323 -0
  152. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleService.test.ts +115 -0
  153. package/Tests/Server/Services/ServiceLevelObjectiveMonitorRuleTriggers.test.ts +21 -2
  154. package/Tests/Server/Services/ServiceLevelObjectiveMonitorTypePostgres.test.ts +480 -0
  155. package/Tests/Server/Services/ServiceLevelObjectiveService.test.ts +162 -0
  156. package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
  157. package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
  158. package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +45 -6
  159. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
  160. package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
  161. package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
  162. package/Tests/Server/Types/Database/FeedEventTypeFilterQuery.test.ts +745 -0
  163. package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
  164. package/Tests/Server/Types/Markdown.test.ts +183 -1
  165. package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +49 -0
  166. package/Tests/Server/Types/Workflow/Components/TelegramSendMessageToChat.test.ts +331 -0
  167. package/Tests/Server/Utils/AI/SloTools.test.ts +10 -0
  168. package/Tests/Server/Utils/CommunityEditionSsoReport.test.ts +565 -0
  169. package/Tests/Server/Utils/EditionEnforcement.test.ts +303 -0
  170. package/Tests/Server/Utils/FrontendEnvironment.test.ts +367 -0
  171. package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +38 -418
  172. package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +518 -0
  173. package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +24 -4
  174. package/Tests/Server/Utils/Monitor/Criteria/MetricMonitorCriteriaAnomalyUnits.test.ts +1 -1
  175. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +1339 -96
  176. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorBreachingSamples.test.ts +1101 -0
  177. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluatorMetricUnits.test.ts +106 -80
  178. package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -0
  179. package/Tests/Server/Utils/Monitor/RootCauseList.test.ts +252 -0
  180. package/Tests/Server/Utils/Rules/RuleRun/RuleRunPermission.test.ts +154 -0
  181. package/Tests/Server/Utils/SSRFProtection.test.ts +111 -0
  182. package/Tests/Server/Utils/Slo/SloRulePatternValidator.test.ts +67 -0
  183. package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +213 -0
  184. package/Tests/Server/Utils/Workspace/Slack/SlackMarkdownSectionSplit.test.ts +1209 -0
  185. package/Tests/Types/API/HostnameFromAuthority.test.ts +20 -10
  186. package/Tests/Types/API/HostnameIPv6.test.ts +149 -0
  187. package/Tests/Types/API/Route.test.ts +56 -0
  188. package/Tests/Types/API/URLSchemeLikePath.test.ts +304 -0
  189. package/Tests/Types/Database/CanonicalModelInstance.test.ts +190 -0
  190. package/Tests/UI/Components/EditionLabelLapseCopy.ts +104 -0
  191. package/Tests/UI/Components/EditionLabelLicenseManagerWiring.test.tsx +254 -0
  192. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +84 -178
  193. package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +1586 -0
  194. package/Tests/UI/Components/EditionLabelLicenseWritesGuard.test.tsx +157 -0
  195. package/Tests/UI/Components/FeedOptions.test.ts +1404 -0
  196. package/Tests/UI/Components/FeedOptionsButton.test.tsx +2603 -0
  197. package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +49 -2
  198. package/Tests/UI/Components/Icon.test.tsx +26 -0
  199. package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
  200. package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
  201. package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
  202. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
  203. package/Tests/UI/Components/useFeedItemsViewKey.test.tsx +1017 -0
  204. package/Tests/UI/Components/useFeedOptions.test.tsx +1107 -0
  205. package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
  206. package/Tests/Utils/HostAddressUtil.test.ts +138 -0
  207. package/Tests/Utils/LabelRuleImportExport.test.ts +102 -0
  208. package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
  209. package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
  210. package/Tests/Utils/Slo/SloDuration.test.ts +115 -24
  211. package/Tests/Utils/Slo/SloHealth.test.ts +93 -10
  212. package/Tests/Utils/Slo/SloMonitorRuleCriteria.test.ts +109 -0
  213. package/Tests/Utils/Slo/SloOverviewText.test.ts +64 -0
  214. package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
  215. package/Types/API/Hostname.ts +63 -16
  216. package/Types/API/Route.ts +19 -2
  217. package/Types/API/URL.ts +26 -2
  218. package/Types/Database/AccessControl/ColumnAccessControl.ts +19 -7
  219. package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +19 -7
  220. package/Types/Database/AccessControl/OwnerOnlyColumn.ts +15 -6
  221. package/Types/Database/CanonicalModelInstance.ts +102 -0
  222. package/Types/Database/TableColumn.ts +20 -6
  223. package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +29 -0
  224. package/Types/IP/IPv6.ts +6 -1
  225. package/Types/Monitor/MetricMonitor/MetricCriteriaContext.ts +6 -5
  226. package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +9 -0
  227. package/Types/Monitor/MonitorStep.ts +6 -1
  228. package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
  229. package/Types/Permission.ts +90 -0
  230. package/Types/Rules/RuleCriteriaFieldRegistry.ts +11 -0
  231. package/Types/Rules/RuleRun.ts +4 -0
  232. package/Types/StatusPage/UptimeDailyAggregate.ts +110 -0
  233. package/UI/Components/EditionLabel/EditionLabel.tsx +796 -1195
  234. package/UI/Components/EditionLabel/LicenseManager.ts +119 -0
  235. package/UI/Components/Feed/FeedOptions.ts +427 -0
  236. package/UI/Components/Feed/FeedOptionsButton.tsx +692 -0
  237. package/UI/Components/Feed/useFeedItems.ts +28 -9
  238. package/UI/Components/Feed/useFeedOptions.ts +225 -0
  239. package/UI/Components/Graphs/DayUptimeGraph.tsx +123 -15
  240. package/UI/Components/Icon/Icon.tsx +1 -1
  241. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  242. package/UI/Components/ModelList/ModelList.tsx +11 -1
  243. package/UI/Components/MonitorGraphs/Uptime.tsx +69 -0
  244. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +28 -12
  245. package/UI/esbuild-enterprise.js +263 -0
  246. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +7 -2
  247. package/Utils/HostAddressUtil.ts +94 -0
  248. package/Utils/LabelRuleImportExport.ts +27 -9
  249. package/Utils/Monitor/MetricValueFormatter.ts +2 -2
  250. package/Utils/Monitor/MonitorDestinationUtil.ts +157 -0
  251. package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
  252. package/Utils/Rules/MonitorTypeRuleCriteria.ts +31 -0
  253. package/Utils/Slo/SloDuration.ts +22 -6
  254. package/Utils/Slo/SloHealth.ts +8 -7
  255. package/Utils/Slo/SloMonitorRuleCriteria.ts +33 -1
  256. package/Utils/Slo/SloOverviewText.ts +33 -0
  257. package/Utils/Slo/SloProjection.ts +4 -3
  258. package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +192 -0
  259. package/build/dist/Models/AnalyticsModels/AuditLog.js +23 -15
  260. package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
  261. package/build/dist/Models/DatabaseModels/GlobalConfig.js +25 -0
  262. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  263. package/build/dist/Models/DatabaseModels/Index.js +4 -0
  264. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  265. package/build/dist/Models/DatabaseModels/Monitor.js +2 -2
  266. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  267. package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -1
  268. package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
  269. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js +2 -0
  270. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveFeed.js.map +1 -1
  271. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js +530 -0
  272. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveLabelRule.js.map +1 -0
  273. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js +39 -4
  274. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveMonitorRule.js.map +1 -1
  275. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js +612 -0
  276. package/build/dist/Models/DatabaseModels/ServiceLevelObjectiveOwnerRule.js.map +1 -0
  277. package/build/dist/Server/API/BaseAPI.js +26 -5
  278. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  279. package/build/dist/Server/API/GlobalConfigAPI.js +148 -344
  280. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  281. package/build/dist/Server/API/ProjectOIDC.js +24 -16
  282. package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
  283. package/build/dist/Server/API/ProjectSSO.js +24 -16
  284. package/build/dist/Server/API/ProjectSSO.js.map +1 -1
  285. package/build/dist/Server/API/StatusPageAPI.js +93 -43
  286. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  287. package/build/dist/Server/API/TeamMemberAPI.js +8 -1
  288. package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
  289. package/build/dist/Server/Enterprise/EnterpriseEdition.js +466 -0
  290. package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -0
  291. package/build/dist/Server/Enterprise/EnterpriseFeature.js +39 -0
  292. package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -0
  293. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +70 -0
  294. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js.map +1 -0
  295. package/build/dist/Server/Enterprise/EnterpriseServerModule.js +84 -0
  296. package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -0
  297. package/build/dist/Server/EnvironmentConfig.js +84 -2
  298. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  299. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js +18 -0
  300. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js.map +1 -0
  301. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js +93 -0
  302. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794100000000-AddSloLabelAndOwnerRules.js.map +1 -0
  303. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js +12 -0
  304. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1794200000000-AddSloMonitorRuleMonitorType.js.map +1 -0
  305. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  306. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  307. package/build/dist/Server/Middleware/UserAuthorization.js +30 -11
  308. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  309. package/build/dist/Server/Services/AuditLogService.js +71 -740
  310. package/build/dist/Server/Services/AuditLogService.js.map +1 -1
  311. package/build/dist/Server/Services/DatabaseService.js +7 -0
  312. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  313. package/build/dist/Server/Services/EnterpriseLicenseService.js +34 -0
  314. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  315. package/build/dist/Server/Services/GlobalConfigService.js +63 -0
  316. package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
  317. package/build/dist/Server/Services/Index.js +4 -0
  318. package/build/dist/Server/Services/Index.js.map +1 -1
  319. package/build/dist/Server/Services/MonitorProbeService.js +90 -17
  320. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  321. package/build/dist/Server/Services/MonitorService.js +48 -6
  322. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  323. package/build/dist/Server/Services/MonitorStatusTimelineService.js +242 -0
  324. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  325. package/build/dist/Server/Services/MonitorTemplateService.js +16 -0
  326. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  327. package/build/dist/Server/Services/ProjectService.js +214 -0
  328. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  329. package/build/dist/Server/Services/RumSessionPinService.js +24 -6
  330. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  331. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js +295 -0
  332. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleEngineService.js.map +1 -0
  333. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js +56 -0
  334. package/build/dist/Server/Services/ServiceLevelObjectiveLabelRuleService.js.map +1 -0
  335. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js +59 -14
  336. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleEngineService.js.map +1 -1
  337. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js +22 -1
  338. package/build/dist/Server/Services/ServiceLevelObjectiveMonitorRuleService.js.map +1 -1
  339. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js +400 -0
  340. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleEngineService.js.map +1 -0
  341. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js +56 -0
  342. package/build/dist/Server/Services/ServiceLevelObjectiveOwnerRuleService.js.map +1 -0
  343. package/build/dist/Server/Services/ServiceLevelObjectiveService.js +21 -0
  344. package/build/dist/Server/Services/ServiceLevelObjectiveService.js.map +1 -1
  345. package/build/dist/Server/Services/StatusPagePrivateUserService.js +7 -3
  346. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  347. package/build/dist/Server/Services/StatusPageService.js +71 -0
  348. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  349. package/build/dist/Server/Services/TeamMemberService.js +10 -0
  350. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  351. package/build/dist/Server/Services/TeamService.js +9 -0
  352. package/build/dist/Server/Services/TeamService.js.map +1 -1
  353. package/build/dist/Server/Services/UserService.js +10 -16
  354. package/build/dist/Server/Services/UserService.js.map +1 -1
  355. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +10 -0
  356. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  357. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +154 -14
  358. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
  359. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +10 -3
  360. package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
  361. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +17 -0
  362. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
  363. package/build/dist/Server/Types/Markdown.js +31 -0
  364. package/build/dist/Server/Types/Markdown.js.map +1 -1
  365. package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js +20 -1
  366. package/build/dist/Server/Types/Workflow/Components/Telegram/SendMessageToChat.js.map +1 -1
  367. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js +1 -0
  368. package/build/dist/Server/Utils/AI/Toolbox/SloTools.js.map +1 -1
  369. package/build/dist/Server/Utils/CommunityEditionSsoReport.js +223 -0
  370. package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +1 -0
  371. package/build/dist/Server/Utils/EditionEnforcement.js +187 -0
  372. package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -0
  373. package/build/dist/Server/Utils/FrontendEnvironment.js +31 -2
  374. package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -1
  375. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +6 -193
  376. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -1
  377. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js +67 -0
  378. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
  379. package/build/dist/Server/Utils/Monitor/Criteria/CompareCriteria.js +1 -1
  380. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
  381. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  382. package/build/dist/Server/Utils/Monitor/Criteria/MetricMonitorCriteria.js +1 -1
  383. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +585 -367
  384. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  385. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js +88 -0
  386. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js.map +1 -0
  387. package/build/dist/Server/Utils/Monitor/RootCauseList.js +101 -0
  388. package/build/dist/Server/Utils/Monitor/RootCauseList.js.map +1 -0
  389. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +28 -0
  390. package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
  391. package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js +28 -0
  392. package/build/dist/Server/Utils/Slo/SloRulePatternValidator.js.map +1 -0
  393. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +331 -11
  394. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  395. package/build/dist/Types/API/Hostname.js +59 -11
  396. package/build/dist/Types/API/Hostname.js.map +1 -1
  397. package/build/dist/Types/API/Route.js +18 -2
  398. package/build/dist/Types/API/Route.js.map +1 -1
  399. package/build/dist/Types/API/URL.js +23 -2
  400. package/build/dist/Types/API/URL.js.map +1 -1
  401. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +19 -7
  402. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
  403. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +19 -7
  404. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
  405. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +13 -6
  406. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -1
  407. package/build/dist/Types/Database/CanonicalModelInstance.js +88 -0
  408. package/build/dist/Types/Database/CanonicalModelInstance.js.map +1 -0
  409. package/build/dist/Types/Database/TableColumn.js +19 -6
  410. package/build/dist/Types/Database/TableColumn.js.map +1 -1
  411. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +28 -0
  412. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js.map +1 -0
  413. package/build/dist/Types/IP/IPv6.js +6 -1
  414. package/build/dist/Types/IP/IPv6.js.map +1 -1
  415. package/build/dist/Types/Monitor/MonitorStep.js +5 -0
  416. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  417. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +1 -1
  418. package/build/dist/Types/Permission.js +84 -0
  419. package/build/dist/Types/Permission.js.map +1 -1
  420. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +11 -0
  421. package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
  422. package/build/dist/Types/Rules/RuleRun.js +4 -0
  423. package/build/dist/Types/Rules/RuleRun.js.map +1 -1
  424. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js +32 -0
  425. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js.map +1 -0
  426. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +414 -585
  427. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  428. package/build/dist/UI/Components/EditionLabel/LicenseManager.js +2 -0
  429. package/build/dist/UI/Components/EditionLabel/LicenseManager.js.map +1 -0
  430. package/build/dist/UI/Components/Feed/FeedOptions.js +235 -0
  431. package/build/dist/UI/Components/Feed/FeedOptions.js.map +1 -0
  432. package/build/dist/UI/Components/Feed/FeedOptionsButton.js +346 -0
  433. package/build/dist/UI/Components/Feed/FeedOptionsButton.js.map +1 -0
  434. package/build/dist/UI/Components/Feed/useFeedItems.js +17 -7
  435. package/build/dist/UI/Components/Feed/useFeedItems.js.map +1 -1
  436. package/build/dist/UI/Components/Feed/useFeedOptions.js +130 -0
  437. package/build/dist/UI/Components/Feed/useFeedOptions.js.map +1 -0
  438. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +90 -17
  439. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
  440. package/build/dist/UI/Components/Icon/Icon.js +1 -1
  441. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  442. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  443. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  444. package/build/dist/UI/Components/ModelList/ModelList.js +4 -1
  445. package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
  446. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +42 -1
  447. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  448. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +2 -2
  449. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  450. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +6 -2
  451. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  452. package/build/dist/Utils/HostAddressUtil.js +80 -0
  453. package/build/dist/Utils/HostAddressUtil.js.map +1 -0
  454. package/build/dist/Utils/LabelRuleImportExport.js +22 -6
  455. package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
  456. package/build/dist/Utils/Monitor/MetricValueFormatter.js +2 -2
  457. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js +127 -0
  458. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js.map +1 -0
  459. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js +374 -0
  460. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js.map +1 -0
  461. package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js +18 -0
  462. package/build/dist/Utils/Rules/MonitorTypeRuleCriteria.js.map +1 -0
  463. package/build/dist/Utils/Slo/SloDuration.js +13 -5
  464. package/build/dist/Utils/Slo/SloDuration.js.map +1 -1
  465. package/build/dist/Utils/Slo/SloHealth.js +8 -7
  466. package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
  467. package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js +16 -1
  468. package/build/dist/Utils/Slo/SloMonitorRuleCriteria.js.map +1 -1
  469. package/build/dist/Utils/Slo/SloOverviewText.js +16 -0
  470. package/build/dist/Utils/Slo/SloOverviewText.js.map +1 -1
  471. package/build/dist/Utils/Slo/SloProjection.js.map +1 -1
  472. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
  473. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -0
  474. package/jest.config.json +3 -1
  475. package/package.json +1 -1
  476. package/test-setup.sh +103 -34
  477. package/tsconfig.json +13 -0
  478. package/Server/API/EnterpriseLicenseAPI.ts +0 -925
  479. package/Server/API/TeamComplianceAPI.ts +0 -158
  480. package/Server/Middleware/SCIMAuthorization.ts +0 -141
  481. package/Server/Services/TeamComplianceService.ts +0 -733
  482. package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +0 -186
  483. package/Server/Utils/InstanceHealth/PostgresHealth.ts +0 -286
  484. package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +0 -451
  485. package/Tests/App/Dashboard/AuditLogsTable.test.tsx +0 -598
  486. package/Tests/App/Dashboard/SecurityEventsExplorer.test.tsx +0 -761
  487. package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +0 -247
  488. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +0 -382
  489. package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +0 -321
  490. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +0 -1851
  491. package/Tests/Server/Middleware/SCIMAuthorization.test.ts +0 -525
  492. package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +0 -1845
  493. package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +0 -495
  494. package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +0 -337
  495. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +0 -576
  496. package/Tests/Utils/EnterpriseLicenseSync.test.ts +0 -568
  497. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +0 -287
  498. package/Utils/EnterpriseLicense/EnterpriseLicenseSync.ts +0 -244
  499. package/build/dist/Server/API/EnterpriseLicenseAPI.js +0 -646
  500. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +0 -1
  501. package/build/dist/Server/API/TeamComplianceAPI.js +0 -111
  502. package/build/dist/Server/API/TeamComplianceAPI.js.map +0 -1
  503. package/build/dist/Server/Middleware/SCIMAuthorization.js +0 -124
  504. package/build/dist/Server/Middleware/SCIMAuthorization.js.map +0 -1
  505. package/build/dist/Server/Services/TeamComplianceService.js +0 -537
  506. package/build/dist/Server/Services/TeamComplianceService.js.map +0 -1
  507. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +0 -145
  508. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +0 -1
  509. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +0 -194
  510. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +0 -1
  511. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +0 -168
  512. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +0 -1
  513. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js +0 -174
  514. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js.map +0 -1
@@ -0,0 +1,757 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import ts from "typescript";
4
+
5
+ /*
6
+ * The detector behind the "browser requests go through the refresh-aware
7
+ * client" guards. Two suites use it:
8
+ *
9
+ * - packages/App/Tests/FrontendRequestsUseRefreshAwareApi.test.ts scans the
10
+ * core frontends and Common/UI. It runs in the App Test job, where ee/ is
11
+ * deleted.
12
+ * - ee/Tests/Server/FrontendRequestsUseRefreshAwareApi.test.ts scans the
13
+ * Enterprise screens (ee/Dashboard, ee/AdminDashboard) that the Community
14
+ * / Enterprise split moved out of the core frontends.
15
+ *
16
+ * Why the rule exists: the access-token cookie lives exactly as long as the
17
+ * 15-minute JWT inside it, so a Dashboard left open past that sends its next
18
+ * request with no access token at all. The server answers 401, and the UI
19
+ * client (Common/UI/Utils/API/API, class BaseAPI) answers that by refreshing
20
+ * the session once and replaying the request - the user never notices.
21
+ *
22
+ * The core client underneath it (Common/Utils/API) cannot do that. Its
23
+ * tryRefreshAuth returns false and its handleError does nothing, because it
24
+ * is also the server's HTTP client and has no session to refresh. A page that
25
+ * imports it directly therefore works for fifteen minutes and then fails. The
26
+ * same happens to a raw fetch(), axios or XMLHttpRequest call: none of them
27
+ * know the session can be refreshed.
28
+ *
29
+ * This module holds the detector only - file listing, the two syntax checks,
30
+ * and the allowlist plumbing. Each suite keeps its own roots and its own
31
+ * allowlist entries, each with a reason a reviewer would accept.
32
+ *
33
+ * It lives under Common/Tests so both suites reach it through the "Common/..."
34
+ * specifier: core never imports ee/, and ee/ imports core only through the
35
+ * package specifiers.
36
+ */
37
+
38
+ // packages/Common, found from this file so every path below shares one origin.
39
+ export const COMMON_DIR: string = path.resolve(__dirname, "..", "..");
40
+
41
+ // packages/
42
+ export const PACKAGES_DIR: string = path.resolve(COMMON_DIR, "..");
43
+
44
+ /* The core client: no session, so no refresh. */
45
+ export const BARE_CLIENT: string = path.join(COMMON_DIR, "Utils", "API.ts");
46
+
47
+ export interface AllowlistEntry {
48
+ // Path relative to the suite's base directory, with "/" separators.
49
+ file: string;
50
+ reason: string;
51
+ }
52
+
53
+ export interface Finding {
54
+ line: number;
55
+ description: string;
56
+ }
57
+
58
+ /* Globals that send a request carrying the session cookie. */
59
+ const RAW_TRANSPORT_GLOBALS: ReadonlySet<string> = new Set<string>([
60
+ "fetch",
61
+ "XMLHttpRequest",
62
+ "EventSource",
63
+ ]);
64
+
65
+ /* Receivers through which those globals are reachable by property access. */
66
+ const GLOBAL_OBJECTS: ReadonlySet<string> = new Set<string>([
67
+ "window",
68
+ "globalThis",
69
+ "self",
70
+ ]);
71
+
72
+ /*
73
+ * Every finding below spells one of these words, so a module without any of
74
+ * them needs no parse.
75
+ */
76
+ const RAW_TRANSPORT_HINT: RegExp =
77
+ /fetch|XMLHttpRequest|EventSource|sendBeacon|axios/;
78
+
79
+ /* A file's path relative to baseDir, with "/" separators on every platform. */
80
+ export function toRelativePath(baseDir: string, filePath: string): string {
81
+ return path.relative(baseDir, filePath).split(path.sep).join("/");
82
+ }
83
+
84
+ /* The inverse of toRelativePath. */
85
+ export function fromRelativePath(baseDir: string, relative: string): string {
86
+ return path.join(baseDir, ...relative.split("/"));
87
+ }
88
+
89
+ /*
90
+ * Every .ts / .tsx module under a directory. node_modules and __mocks__ are
91
+ * never browser code, and neither is src/Server under StatusPage and
92
+ * PublicDashboard: that is the node side that renders those pages, where the
93
+ * core client is correct.
94
+ */
95
+ export function listSourceFiles(directory: string): Array<string> {
96
+ const found: Array<string> = [];
97
+
98
+ for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
99
+ const full: string = path.join(directory, entry.name);
100
+
101
+ if (entry.isDirectory()) {
102
+ if (
103
+ entry.name === "node_modules" ||
104
+ entry.name === "__mocks__" ||
105
+ (entry.name === "Server" && path.basename(directory) === "src")
106
+ ) {
107
+ continue;
108
+ }
109
+ found.push(...listSourceFiles(full));
110
+ continue;
111
+ }
112
+
113
+ if (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx")) {
114
+ found.push(full);
115
+ }
116
+ }
117
+
118
+ return found;
119
+ }
120
+
121
+ /* Each file's text, keyed by its absolute path. */
122
+ export function readSources(files: Array<string>): Map<string, string> {
123
+ return new Map<string, string>(
124
+ files.map((file: string): [string, string] => {
125
+ return [file, fs.readFileSync(file, "utf8")];
126
+ }),
127
+ );
128
+ }
129
+
130
+ /*
131
+ * Both scans below walk the same few thousand modules; parse each once. Keyed
132
+ * by path and checked against the text, so a fixture can never be answered
133
+ * with a stale tree.
134
+ */
135
+ const parsedSources: Map<string, { source: string; tree: ts.SourceFile }> =
136
+ new Map<string, { source: string; tree: ts.SourceFile }>();
137
+
138
+ function parse(filePath: string, source: string): ts.SourceFile {
139
+ const cached: { source: string; tree: ts.SourceFile } | undefined =
140
+ parsedSources.get(filePath);
141
+
142
+ if (cached && cached.source === source) {
143
+ return cached.tree;
144
+ }
145
+
146
+ const tree: ts.SourceFile = ts.createSourceFile(
147
+ filePath,
148
+ source,
149
+ ts.ScriptTarget.Latest,
150
+ true,
151
+ filePath.endsWith(".tsx") ? ts.ScriptKind.TSX : ts.ScriptKind.TS,
152
+ );
153
+
154
+ parsedSources.set(filePath, { source: source, tree: tree });
155
+
156
+ return tree;
157
+ }
158
+
159
+ /*
160
+ * Resolve a specifier the way the feature-set bundles do: "Common/*" is the
161
+ * Common package, relative paths try .ts, .tsx and /index. Anything else is a
162
+ * node module and never the core client.
163
+ */
164
+ function resolveSpecifier(fromFile: string, specifier: string): string | null {
165
+ let base: string;
166
+
167
+ if (specifier.startsWith("Common/")) {
168
+ base = path.join(COMMON_DIR, specifier.slice("Common/".length));
169
+ } else if (specifier.startsWith(".")) {
170
+ base = path.resolve(path.dirname(fromFile), specifier);
171
+ } else {
172
+ return null;
173
+ }
174
+
175
+ for (const candidate of [
176
+ base,
177
+ `${base}.ts`,
178
+ `${base}.tsx`,
179
+ path.join(base, "index.ts"),
180
+ path.join(base, "index.tsx"),
181
+ ]) {
182
+ if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
183
+ return candidate;
184
+ }
185
+ }
186
+
187
+ return null;
188
+ }
189
+
190
+ /*
191
+ * The core client is Common/Utils/API.ts, so any specifier that reaches it
192
+ * ends in "API". Checking that first keeps the scan from touching the disk
193
+ * for every one of the thousands of other imports.
194
+ */
195
+ function mightNameBareClient(specifier: string): boolean {
196
+ const lastSegment: string = specifier.split("/").pop() || "";
197
+
198
+ return lastSegment === "API" || lastSegment === "API.ts";
199
+ }
200
+
201
+ function lineOf(sourceFile: ts.SourceFile, node: ts.Node): number {
202
+ return (
203
+ sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1
204
+ );
205
+ }
206
+
207
+ /* `import(x)`, `require(x)` and jest's require helpers: the whole module. */
208
+ function getDynamicModuleSpecifier(node: ts.Node): string | null {
209
+ if (!ts.isCallExpression(node)) {
210
+ return null;
211
+ }
212
+
213
+ const isModuleLoader: boolean =
214
+ node.expression.kind === ts.SyntaxKind.ImportKeyword ||
215
+ (ts.isIdentifier(node.expression) && node.expression.text === "require") ||
216
+ (ts.isPropertyAccessExpression(node.expression) &&
217
+ ts.isIdentifier(node.expression.expression) &&
218
+ node.expression.expression.text === "jest" &&
219
+ (node.expression.name.text === "requireActual" ||
220
+ node.expression.name.text === "requireMock"));
221
+
222
+ const firstArgument: ts.Expression | undefined = node.arguments[0];
223
+
224
+ if (
225
+ !isModuleLoader ||
226
+ !firstArgument ||
227
+ !ts.isStringLiteralLike(firstArgument)
228
+ ) {
229
+ return null;
230
+ }
231
+
232
+ return firstArgument.text;
233
+ }
234
+
235
+ function importsDefaultAsValue(importClause: ts.ImportClause): boolean {
236
+ if (importClause.isTypeOnly) {
237
+ return false;
238
+ }
239
+
240
+ if (importClause.name) {
241
+ return true;
242
+ }
243
+
244
+ const bindings: ts.NamedImportBindings | undefined =
245
+ importClause.namedBindings;
246
+
247
+ if (!bindings) {
248
+ return false;
249
+ }
250
+
251
+ /* `import * as Core` hands over Core.default, the class itself. */
252
+ if (ts.isNamespaceImport(bindings)) {
253
+ return true;
254
+ }
255
+
256
+ return bindings.elements.some((element: ts.ImportSpecifier): boolean => {
257
+ return (
258
+ !element.isTypeOnly &&
259
+ (element.propertyName ?? element.name).text === "default"
260
+ );
261
+ });
262
+ }
263
+
264
+ function exportsDefaultAsValue(declaration: ts.ExportDeclaration): boolean {
265
+ if (declaration.isTypeOnly || !declaration.exportClause) {
266
+ /* `export * from` never re-exports a default. */
267
+ return false;
268
+ }
269
+
270
+ if (ts.isNamespaceExport(declaration.exportClause)) {
271
+ return true;
272
+ }
273
+
274
+ return declaration.exportClause.elements.some(
275
+ (element: ts.ExportSpecifier): boolean => {
276
+ return (
277
+ !element.isTypeOnly &&
278
+ (element.propertyName ?? element.name).text === "default"
279
+ );
280
+ },
281
+ );
282
+ }
283
+
284
+ /*
285
+ * Every place a module gets hold of the core client class. Parsed rather than
286
+ * grepped so a comment or a code sample quoting the import cannot trip it,
287
+ * and so `import type` and named imports of the core module's interfaces
288
+ * pass: those carry no client.
289
+ */
290
+ export function findBareClientValueImports(
291
+ filePath: string,
292
+ source: string,
293
+ ): Array<Finding> {
294
+ /*
295
+ * Cheap exit first: this runs over every browser module, and one that never
296
+ * spells "API" cannot be importing Common/Utils/API.
297
+ */
298
+ if (!source.includes("API")) {
299
+ return [];
300
+ }
301
+
302
+ const sourceFile: ts.SourceFile = parse(filePath, source);
303
+ const findings: Array<Finding> = [];
304
+
305
+ const isBareClient: (specifier: string) => boolean = (
306
+ specifier: string,
307
+ ): boolean => {
308
+ return (
309
+ mightNameBareClient(specifier) &&
310
+ resolveSpecifier(filePath, specifier) === BARE_CLIENT
311
+ );
312
+ };
313
+
314
+ const visit: (node: ts.Node) => void = (node: ts.Node): void => {
315
+ if (
316
+ ts.isImportDeclaration(node) &&
317
+ ts.isStringLiteralLike(node.moduleSpecifier) &&
318
+ isBareClient(node.moduleSpecifier.text) &&
319
+ node.importClause &&
320
+ importsDefaultAsValue(node.importClause)
321
+ ) {
322
+ findings.push({
323
+ line: lineOf(sourceFile, node),
324
+ description: `imports the core client from "${node.moduleSpecifier.text}"`,
325
+ });
326
+ } else if (
327
+ ts.isExportDeclaration(node) &&
328
+ node.moduleSpecifier &&
329
+ ts.isStringLiteralLike(node.moduleSpecifier) &&
330
+ isBareClient(node.moduleSpecifier.text) &&
331
+ exportsDefaultAsValue(node)
332
+ ) {
333
+ findings.push({
334
+ line: lineOf(sourceFile, node),
335
+ description: `re-exports the core client from "${node.moduleSpecifier.text}"`,
336
+ });
337
+ } else if (
338
+ ts.isImportEqualsDeclaration(node) &&
339
+ !node.isTypeOnly &&
340
+ ts.isExternalModuleReference(node.moduleReference) &&
341
+ ts.isStringLiteralLike(node.moduleReference.expression) &&
342
+ isBareClient(node.moduleReference.expression.text)
343
+ ) {
344
+ findings.push({
345
+ line: lineOf(sourceFile, node),
346
+ description: `requires the core client from "${node.moduleReference.expression.text}"`,
347
+ });
348
+ } else {
349
+ const dynamicSpecifier: string | null = getDynamicModuleSpecifier(node);
350
+
351
+ if (dynamicSpecifier !== null && isBareClient(dynamicSpecifier)) {
352
+ findings.push({
353
+ line: lineOf(sourceFile, node),
354
+ description: `loads the core client from "${dynamicSpecifier}"`,
355
+ });
356
+ }
357
+ }
358
+
359
+ ts.forEachChild(node, visit);
360
+ };
361
+
362
+ visit(sourceFile);
363
+
364
+ return findings;
365
+ }
366
+
367
+ /* Any reference to the core module at all, types included. */
368
+ export function referencesBareClient(
369
+ filePath: string,
370
+ source: string,
371
+ ): boolean {
372
+ const sourceFile: ts.SourceFile = parse(filePath, source);
373
+
374
+ return sourceFile.statements.some((statement: ts.Statement): boolean => {
375
+ if (
376
+ !ts.isImportDeclaration(statement) &&
377
+ !ts.isExportDeclaration(statement)
378
+ ) {
379
+ return false;
380
+ }
381
+
382
+ const specifier: ts.Expression | undefined = statement.moduleSpecifier;
383
+
384
+ return (
385
+ specifier !== undefined &&
386
+ ts.isStringLiteralLike(specifier) &&
387
+ resolveSpecifier(filePath, specifier.text) === BARE_CLIENT
388
+ );
389
+ });
390
+ }
391
+
392
+ function collectBindingNames(name: ts.BindingName, into: Set<string>): void {
393
+ if (ts.isIdentifier(name)) {
394
+ into.add(name.text);
395
+ return;
396
+ }
397
+
398
+ for (const element of name.elements) {
399
+ if (ts.isBindingElement(element)) {
400
+ collectBindingNames(element.name, into);
401
+ }
402
+ }
403
+ }
404
+
405
+ function namesDeclaredByStatements(
406
+ statements: ts.NodeArray<ts.Statement>,
407
+ ): Set<string> {
408
+ const names: Set<string> = new Set<string>();
409
+
410
+ for (const statement of statements) {
411
+ if (ts.isVariableStatement(statement)) {
412
+ for (const declaration of statement.declarationList.declarations) {
413
+ collectBindingNames(declaration.name, names);
414
+ }
415
+ } else if (
416
+ (ts.isFunctionDeclaration(statement) ||
417
+ ts.isClassDeclaration(statement) ||
418
+ ts.isEnumDeclaration(statement)) &&
419
+ statement.name
420
+ ) {
421
+ names.add(statement.name.text);
422
+ } else if (ts.isImportDeclaration(statement) && statement.importClause) {
423
+ const clause: ts.ImportClause = statement.importClause;
424
+
425
+ if (clause.name) {
426
+ names.add(clause.name.text);
427
+ }
428
+
429
+ if (clause.namedBindings) {
430
+ if (ts.isNamespaceImport(clause.namedBindings)) {
431
+ names.add(clause.namedBindings.name.text);
432
+ } else {
433
+ for (const element of clause.namedBindings.elements) {
434
+ names.add(element.name.text);
435
+ }
436
+ }
437
+ }
438
+ }
439
+ }
440
+
441
+ return names;
442
+ }
443
+
444
+ function namesDeclaredByScope(scope: ts.Node): Set<string> {
445
+ if (
446
+ ts.isSourceFile(scope) ||
447
+ ts.isBlock(scope) ||
448
+ ts.isModuleBlock(scope) ||
449
+ ts.isCaseClause(scope) ||
450
+ ts.isDefaultClause(scope)
451
+ ) {
452
+ return namesDeclaredByStatements(scope.statements);
453
+ }
454
+
455
+ const names: Set<string> = new Set<string>();
456
+
457
+ if (ts.isFunctionLike(scope)) {
458
+ for (const parameter of scope.parameters) {
459
+ collectBindingNames(parameter.name, names);
460
+ }
461
+
462
+ if (ts.isFunctionExpression(scope) && scope.name) {
463
+ names.add(scope.name.text);
464
+ }
465
+ } else if (
466
+ (ts.isForStatement(scope) ||
467
+ ts.isForInStatement(scope) ||
468
+ ts.isForOfStatement(scope)) &&
469
+ scope.initializer &&
470
+ ts.isVariableDeclarationList(scope.initializer)
471
+ ) {
472
+ for (const declaration of scope.initializer.declarations) {
473
+ collectBindingNames(declaration.name, names);
474
+ }
475
+ } else if (ts.isCatchClause(scope) && scope.variableDeclaration) {
476
+ collectBindingNames(scope.variableDeclaration.name, names);
477
+ }
478
+
479
+ return names;
480
+ }
481
+
482
+ /*
483
+ * `const fetch = async () => {...}; void fetch();` is a local loader, not the
484
+ * global - ExceptionsNavTabs does exactly that. Walk the enclosing scopes and
485
+ * only report the global when nothing between here and the file declares it.
486
+ */
487
+ function isDeclaredInEnclosingScope(node: ts.Node, name: string): boolean {
488
+ let current: ts.Node | undefined = node.parent;
489
+
490
+ while (current) {
491
+ if (namesDeclaredByScope(current).has(name)) {
492
+ return true;
493
+ }
494
+ current = current.parent;
495
+ }
496
+
497
+ return false;
498
+ }
499
+
500
+ function isAxios(specifier: string): boolean {
501
+ return specifier === "axios" || specifier.startsWith("axios/");
502
+ }
503
+
504
+ /*
505
+ * FilePicker imports AxiosProgressEvent as a type; that sends nothing. Only a
506
+ * binding that exists at runtime can make a request.
507
+ */
508
+ function importsAnyValue(importClause: ts.ImportClause): boolean {
509
+ if (importClause.isTypeOnly) {
510
+ return false;
511
+ }
512
+
513
+ if (importClause.name) {
514
+ return true;
515
+ }
516
+
517
+ const bindings: ts.NamedImportBindings | undefined =
518
+ importClause.namedBindings;
519
+
520
+ if (!bindings) {
521
+ return false;
522
+ }
523
+
524
+ if (ts.isNamespaceImport(bindings)) {
525
+ return true;
526
+ }
527
+
528
+ return bindings.elements.some((element: ts.ImportSpecifier): boolean => {
529
+ return !element.isTypeOnly;
530
+ });
531
+ }
532
+
533
+ function getGlobalMemberName(node: ts.Node): string | null {
534
+ if (
535
+ ts.isPropertyAccessExpression(node) &&
536
+ ts.isIdentifier(node.expression) &&
537
+ GLOBAL_OBJECTS.has(node.expression.text)
538
+ ) {
539
+ return node.name.text;
540
+ }
541
+
542
+ if (
543
+ ts.isElementAccessExpression(node) &&
544
+ ts.isIdentifier(node.expression) &&
545
+ GLOBAL_OBJECTS.has(node.expression.text) &&
546
+ ts.isStringLiteralLike(node.argumentExpression)
547
+ ) {
548
+ return node.argumentExpression.text;
549
+ }
550
+
551
+ return null;
552
+ }
553
+
554
+ /*
555
+ * Requests that bypass every client: the global fetch (bare or through
556
+ * window / globalThis / self), XMLHttpRequest, EventSource,
557
+ * navigator.sendBeacon, and axios loaded as a value. Strings and comments are
558
+ * never syntax, so the code samples on the telemetry and monitor pages - which
559
+ * quote fetch and axios for the reader to copy - do not count.
560
+ */
561
+ export function findRawTransports(
562
+ filePath: string,
563
+ source: string,
564
+ ): Array<Finding> {
565
+ if (!RAW_TRANSPORT_HINT.test(source)) {
566
+ return [];
567
+ }
568
+
569
+ const sourceFile: ts.SourceFile = parse(filePath, source);
570
+ const findings: Array<Finding> = [];
571
+
572
+ const visit: (node: ts.Node) => void = (node: ts.Node): void => {
573
+ const globalMember: string | null = getGlobalMemberName(node);
574
+
575
+ if (globalMember !== null && RAW_TRANSPORT_GLOBALS.has(globalMember)) {
576
+ findings.push({
577
+ line: lineOf(sourceFile, node),
578
+ description: `uses ${node.getText(sourceFile)}`,
579
+ });
580
+ } else if (
581
+ ts.isCallExpression(node) &&
582
+ ts.isIdentifier(node.expression) &&
583
+ node.expression.text === "fetch" &&
584
+ !isDeclaredInEnclosingScope(node, "fetch")
585
+ ) {
586
+ findings.push({
587
+ line: lineOf(sourceFile, node),
588
+ description: "calls the global fetch()",
589
+ });
590
+ } else if (
591
+ ts.isNewExpression(node) &&
592
+ ts.isIdentifier(node.expression) &&
593
+ RAW_TRANSPORT_GLOBALS.has(node.expression.text) &&
594
+ !isDeclaredInEnclosingScope(node, node.expression.text)
595
+ ) {
596
+ findings.push({
597
+ line: lineOf(sourceFile, node),
598
+ description: `constructs ${node.expression.text}`,
599
+ });
600
+ } else if (
601
+ ts.isPropertyAccessExpression(node) &&
602
+ node.name.text === "sendBeacon"
603
+ ) {
604
+ findings.push({
605
+ line: lineOf(sourceFile, node),
606
+ description: `uses ${node.getText(sourceFile)}`,
607
+ });
608
+ } else if (
609
+ ts.isImportDeclaration(node) &&
610
+ ts.isStringLiteralLike(node.moduleSpecifier) &&
611
+ isAxios(node.moduleSpecifier.text) &&
612
+ node.importClause &&
613
+ importsAnyValue(node.importClause)
614
+ ) {
615
+ findings.push({
616
+ line: lineOf(sourceFile, node),
617
+ description: `imports axios from "${node.moduleSpecifier.text}"`,
618
+ });
619
+ } else {
620
+ const dynamicSpecifier: string | null = getDynamicModuleSpecifier(node);
621
+
622
+ if (dynamicSpecifier !== null && isAxios(dynamicSpecifier)) {
623
+ findings.push({
624
+ line: lineOf(sourceFile, node),
625
+ description: `loads axios from "${dynamicSpecifier}"`,
626
+ });
627
+ }
628
+ }
629
+
630
+ ts.forEachChild(node, visit);
631
+ };
632
+
633
+ visit(sourceFile);
634
+
635
+ return findings;
636
+ }
637
+
638
+ export function allowlistedFiles(
639
+ allowlist: ReadonlyArray<AllowlistEntry>,
640
+ ): Set<string> {
641
+ return new Set<string>(
642
+ allowlist.map((entry: AllowlistEntry): string => {
643
+ return entry.file;
644
+ }),
645
+ );
646
+ }
647
+
648
+ /*
649
+ * Allowlist entries that no longer earn their place: the file is gone, or it
650
+ * no longer does what it was excused for. A suite asserts this is empty, so an
651
+ * allowlist cannot quietly outlive its reasons.
652
+ */
653
+ export function findStaleAllowlistEntries(data: {
654
+ baseDir: string;
655
+ bareClientAllowlist: ReadonlyArray<AllowlistEntry>;
656
+ rawTransportAllowlist: ReadonlyArray<AllowlistEntry>;
657
+ }): Array<string> {
658
+ const stale: Array<string> = [];
659
+
660
+ for (const entry of data.bareClientAllowlist) {
661
+ const filePath: string = fromRelativePath(data.baseDir, entry.file);
662
+
663
+ if (!fs.existsSync(filePath)) {
664
+ stale.push(
665
+ `${entry.file} no longer exists - remove it from BARE_CLIENT_ALLOWLIST`,
666
+ );
667
+ continue;
668
+ }
669
+
670
+ if (
671
+ findBareClientValueImports(filePath, fs.readFileSync(filePath, "utf8"))
672
+ .length === 0
673
+ ) {
674
+ stale.push(
675
+ `${entry.file} no longer imports the core client - remove it from BARE_CLIENT_ALLOWLIST`,
676
+ );
677
+ }
678
+ }
679
+
680
+ for (const entry of data.rawTransportAllowlist) {
681
+ const filePath: string = fromRelativePath(data.baseDir, entry.file);
682
+
683
+ if (!fs.existsSync(filePath)) {
684
+ stale.push(
685
+ `${entry.file} no longer exists - remove it from RAW_TRANSPORT_ALLOWLIST`,
686
+ );
687
+ continue;
688
+ }
689
+
690
+ if (
691
+ findRawTransports(filePath, fs.readFileSync(filePath, "utf8")).length ===
692
+ 0
693
+ ) {
694
+ stale.push(
695
+ `${entry.file} no longer makes a raw request - remove it from RAW_TRANSPORT_ALLOWLIST`,
696
+ );
697
+ }
698
+ }
699
+
700
+ return stale;
701
+ }
702
+
703
+ /*
704
+ * One line per module that holds the core client, naming the file, the line
705
+ * and the fix. The strings ARE the failure message: jest prints the received
706
+ * array.
707
+ */
708
+ export function findBareClientOffenders(data: {
709
+ sources: ReadonlyMap<string, string>;
710
+ baseDir: string;
711
+ allowlist: ReadonlyArray<AllowlistEntry>;
712
+ }): Array<string> {
713
+ const allowed: Set<string> = allowlistedFiles(data.allowlist);
714
+ const offenders: Array<string> = [];
715
+
716
+ for (const [file, source] of data.sources) {
717
+ const relative: string = toRelativePath(data.baseDir, file);
718
+
719
+ if (allowed.has(relative)) {
720
+ continue;
721
+ }
722
+
723
+ for (const finding of findBareClientValueImports(file, source)) {
724
+ offenders.push(
725
+ `${relative}:${finding.line} ${finding.description}. Import API from "Common/UI/Utils/API/API" (or the feature's own subclass, e.g. StatusPage/src/Utils/API) instead: the core client never refreshes an expired session, so this request fails once the 15-minute access token lapses.`,
726
+ );
727
+ }
728
+ }
729
+
730
+ return offenders;
731
+ }
732
+
733
+ /* One line per request opened around the client, as above. */
734
+ export function findRawTransportOffenders(data: {
735
+ sources: ReadonlyMap<string, string>;
736
+ baseDir: string;
737
+ allowlist: ReadonlyArray<AllowlistEntry>;
738
+ }): Array<string> {
739
+ const allowed: Set<string> = allowlistedFiles(data.allowlist);
740
+ const offenders: Array<string> = [];
741
+
742
+ for (const [file, source] of data.sources) {
743
+ const relative: string = toRelativePath(data.baseDir, file);
744
+
745
+ if (allowed.has(relative)) {
746
+ continue;
747
+ }
748
+
749
+ for (const finding of findRawTransports(file, source)) {
750
+ offenders.push(
751
+ `${relative}:${finding.line} ${finding.description}. Use API from "Common/UI/Utils/API/API", which refreshes an expired session and replays the request. If the response cannot come through it (binary data, keepalive), call API.refreshSession() on a 401 and add the file to RAW_TRANSPORT_ALLOWLIST with the reason.`,
752
+ );
753
+ }
754
+ }
755
+
756
+ return offenders;
757
+ }