@oneuptime/common 12.0.23 → 12.0.25

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 (323) hide show
  1. package/Models/AnalyticsModels/Span.ts +101 -0
  2. package/Models/DatabaseModels/DetectionRule.ts +55 -0
  3. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +27 -7
  4. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +67 -0
  5. package/Models/DatabaseModels/Project.ts +68 -0
  6. package/Models/DatabaseModels/User.ts +68 -0
  7. package/Server/API/BaseAPI.ts +0 -24
  8. package/Server/API/SlackAPI.ts +0 -2
  9. package/Server/API/TelemetryAPI.ts +29 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.ts +28 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.ts +49 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.ts +33 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  14. package/Server/Middleware/GzipRequestBody.ts +311 -0
  15. package/Server/Middleware/MultipartFormData.ts +87 -3
  16. package/Server/Middleware/SlackAuthorization.ts +96 -18
  17. package/Server/Services/DetectionRuleService.ts +73 -6
  18. package/Server/Services/Index.ts +205 -0
  19. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +59 -0
  20. package/Server/Services/NetworkDeviceService.ts +148 -0
  21. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +65 -0
  22. package/Server/Services/OnCallDutyPolicyFeedService.ts +1 -1
  23. package/Server/Services/ProjectService.ts +29 -19
  24. package/Server/Services/SecurityEventService.ts +90 -13
  25. package/Server/Services/StatusPageResourceService.ts +223 -0
  26. package/Server/Services/TelemetryAttributeService.ts +17 -0
  27. package/Server/Services/UserService.ts +4 -6
  28. package/Server/Types/Markdown.ts +161 -67
  29. package/Server/Utils/AI/Toolbox/OnCallTools.ts +12 -4
  30. package/Server/Utils/AnalyticsDatabase/Statement.ts +13 -1
  31. package/Server/Utils/AnalyticsDatabase/StatementGenerator.ts +297 -6
  32. package/Server/Utils/Attribution.ts +4 -0
  33. package/Server/Utils/Marketing/MarketingEventUtil.ts +45 -7
  34. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +55 -3
  35. package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +21 -0
  36. package/Server/Utils/StartServer.ts +12 -32
  37. package/Server/Utils/Telemetry/LlmCostBudgetEvaluator.ts +101 -4
  38. package/Server/Utils/Telemetry/LlmMetricSpend.ts +181 -0
  39. package/Server/Utils/Telemetry/LlmSpan.ts +46 -0
  40. package/Server/Utils/Workspace/Slack/Actions/Auth.ts +0 -12
  41. package/Server/Views/Partials/AnalyticsConsent.ejs +159 -102
  42. package/Server/Views/Partials/Head.ejs +2 -1
  43. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +776 -38
  44. package/Tests/App/Dashboard/CorrelateFilterBuilder.test.tsx +359 -0
  45. package/Tests/App/Dashboard/CorrelateGraph.test.tsx +865 -0
  46. package/Tests/App/Dashboard/CorrelationGraph.test.ts +346 -0
  47. package/Tests/App/Dashboard/CriteriaFilterConditionDropdown.test.tsx +256 -0
  48. package/Tests/App/Dashboard/CriteriaFilterDefaults.test.ts +738 -0
  49. package/Tests/App/Dashboard/CriteriaFilterMonitorTypeChange.test.ts +1122 -0
  50. package/Tests/App/Dashboard/DiscoveryScanWizardValidation.test.tsx +283 -0
  51. package/Tests/App/Dashboard/ExternalStatusPageCriteriaFilter.test.ts +407 -0
  52. package/Tests/App/Dashboard/LlmCallsTableIdentity.test.tsx +322 -0
  53. package/Tests/App/Dashboard/LlmOverview.test.tsx +335 -0
  54. package/Tests/App/Dashboard/LlmSpanDisplay.test.ts +391 -0
  55. package/Tests/App/Dashboard/LlmUsageBreakdown.test.tsx +1007 -0
  56. package/Tests/App/Dashboard/MetricSeriesInvestigateMenu.test.tsx +5 -14
  57. package/Tests/App/Dashboard/MonitorCriteriaActionToggles.test.tsx +426 -0
  58. package/Tests/App/Dashboard/MonitorStepsCriteriaAlignmentWiring.test.tsx +352 -0
  59. package/Tests/App/Dashboard/OnCallLayerCardOverrides.test.tsx +278 -0
  60. package/Tests/App/Dashboard/OnCallLayerShiftPreviewOverrides.test.ts +237 -0
  61. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +2 -2
  62. package/Tests/App/Dashboard/OnCallSchedulePreviewOverrides.test.tsx +460 -0
  63. package/Tests/App/Dashboard/SecurityEventAttributeUtil.test.ts +171 -0
  64. package/Tests/App/Dashboard/SecurityEventCorrelation.test.ts +857 -0
  65. package/Tests/App/Dashboard/SecurityEventDetailObservables.test.tsx +194 -0
  66. package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +124 -0
  67. package/Tests/App/Dashboard/SecurityEventsMonitorStepForm.test.tsx +79 -19
  68. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +382 -0
  69. package/Tests/App/StatusPage/BulkAddStatusPageMonitors.test.ts +216 -0
  70. package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +590 -11
  71. package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +757 -0
  72. package/Tests/Models/DiscoveryScanNameColumn.test.ts +293 -0
  73. package/Tests/Server/API/BaseAPI.test.ts +41 -0
  74. package/Tests/Server/API/BaseAPIUpdatePayloadValidation.test.ts +9 -16
  75. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +564 -0
  76. package/Tests/Server/Infrastructure/Postgres/SchemaMigrationsOrdering.test.ts +120 -4
  77. package/Tests/Server/Middleware/GzipRequestBody.test.ts +725 -0
  78. package/Tests/Server/Middleware/MultipartFormData.test.ts +298 -0
  79. package/Tests/Server/Middleware/SlackAuthorization.test.ts +262 -5
  80. package/Tests/Server/Services/AddDetectionRuleDistinctCountColumnsMigration.test.ts +311 -0
  81. package/Tests/Server/Services/DetectionRuleService.test.ts +134 -2
  82. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +7 -1
  83. package/Tests/Server/Services/FeedRetentionConsistency.test.ts +131 -0
  84. package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +194 -0
  85. package/Tests/Server/Services/NetworkDeviceMonitorStatusStamp.test.ts +800 -0
  86. package/Tests/Server/Services/OnCallScheduleAttachRosterRefresh.test.ts +244 -0
  87. package/Tests/Server/Services/SecurityEventService.test.ts +376 -0
  88. package/Tests/Server/Services/StatusPageResourceDuplicates.test.ts +703 -0
  89. package/Tests/Server/Services/TelemetryAttributeServiceSecurityEvent.test.ts +256 -0
  90. package/Tests/Server/Types/Workflow/Components/ComponentRegistryParity.test.ts +417 -0
  91. package/Tests/Server/Utils/AnalyticsDatabase/StatementGeneratorWhereOperators.test.ts +677 -0
  92. package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +43 -0
  93. package/Tests/Server/Utils/Monitor/Criteria/ProfileMonitorCriteria.test.ts +15 -11
  94. package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +369 -8
  95. package/Tests/Server/Utils/SecurityEvent/SigmaClickhouseCompiler.test.ts +35 -0
  96. package/Tests/Server/Utils/Telemetry/LlmCostBudgetEvaluator.test.ts +387 -4
  97. package/Tests/Server/Utils/Telemetry/LlmMetricSpend.test.ts +386 -0
  98. package/Tests/Server/Utils/Telemetry/LlmSpan.test.ts +804 -0
  99. package/Tests/Server/Views/AnalyticsConsentPartial.test.ts +48 -5
  100. package/Tests/Types/Code/YamlSyntax.test.ts +396 -0
  101. package/Tests/Types/Monitor/MetricAndProfileDefaultCriteria.test.ts +957 -0
  102. package/Tests/Types/Monitor/MonitorCriteriaActionValidation.test.ts +598 -0
  103. package/Tests/Types/Monitor/MonitorCriteriaInstance.test.ts +49 -0
  104. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +6 -6
  105. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +4 -4
  106. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +4 -3
  107. package/Tests/Types/Telemetry/LlmMetricConventions.test.ts +584 -0
  108. package/Tests/UI/Components/AiInvestigationSettingsCard.test.tsx +0 -12
  109. package/Tests/UI/Components/CardModelDetailEdit.test.tsx +1 -17
  110. package/Tests/UI/Components/CodeEditor.test.tsx +474 -10
  111. package/Tests/UI/Components/Detail/YamlField.test.tsx +105 -0
  112. package/Tests/UI/Components/EntityDropdownLabelsBulkAdd.test.tsx +319 -0
  113. package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +231 -0
  114. package/Tests/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.test.ts +1 -0
  115. package/Tests/UI/Components/Forms/ValidationYAML.test.ts +234 -0
  116. package/Tests/UI/Components/ModelTable/AttributeColumns.test.tsx +573 -0
  117. package/Tests/UI/Components/ModelTable/BaseModelTableAttributeColumns.test.tsx +824 -0
  118. package/Tests/UI/Components/ModelTable/ColumnCustomizationModalAddableColumns.test.tsx +707 -0
  119. package/Tests/UI/Components/SideOver.test.tsx +1 -1
  120. package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +294 -0
  121. package/Tests/UI/Components/StatusPage/ResourceListSelection.test.tsx +436 -0
  122. package/Tests/UI/Components/TableBulkCsvExport.test.tsx +6 -2
  123. package/Tests/UI/Components/Toggle.test.tsx +25 -0
  124. package/Tests/UI/Components/YamlEditor.test.tsx +847 -0
  125. package/Tests/Utils/NetworkDevice/DeviceReachabilityUtil.test.ts +252 -0
  126. package/Tests/Utils/NetworkDiscovery/DiscoveredHostUtil.test.ts +221 -0
  127. package/Tests/Utils/NetworkDiscovery/ScanNameUtil.test.ts +312 -0
  128. package/Tests/Utils/StatusPage/ResourceExplorer.test.ts +468 -0
  129. package/Tests/Utils/Telemetry/LlmMetricQuery.test.ts +770 -0
  130. package/Types/Code/YamlSyntax.ts +396 -0
  131. package/Types/Exception/ExceptionCode.ts +1 -0
  132. package/Types/Exception/PayloadTooLargeException.ts +8 -0
  133. package/Types/Marketing/Attribution.ts +10 -0
  134. package/Types/Marketing/MarketingEvent.ts +4 -0
  135. package/Types/Monitor/MonitorCriteriaInstance.ts +116 -56
  136. package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +2 -1
  137. package/Types/SecurityEvent/DetectionFindingConstants.ts +11 -0
  138. package/Types/Telemetry/LlmConventions.ts +255 -0
  139. package/Types/Telemetry/LlmMetricConventions.ts +329 -0
  140. package/UI/Components/AutocompleteTextInput/AutocompleteTextInput.tsx +3 -0
  141. package/UI/Components/BulkUpdate/BulkUpdateForm.tsx +10 -1
  142. package/UI/Components/CodeEditor/CodeEditor.tsx +241 -79
  143. package/UI/Components/CodeEditor/YamlEditor.tsx +369 -0
  144. package/UI/Components/Detail/Detail.tsx +10 -0
  145. package/UI/Components/EntityDropdown/EntityDropdown.tsx +33 -0
  146. package/UI/Components/Forms/Fields/FormField.tsx +31 -0
  147. package/UI/Components/Forms/Types/Field.ts +8 -0
  148. package/UI/Components/Forms/Types/FormFieldSchemaType.ts +1 -0
  149. package/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.ts +2 -0
  150. package/UI/Components/Forms/Validation.ts +46 -0
  151. package/UI/Components/Input/Input.tsx +3 -0
  152. package/UI/Components/ModelTable/AttributeColumns.tsx +321 -0
  153. package/UI/Components/ModelTable/BaseModelTable.tsx +263 -14
  154. package/UI/Components/ModelTable/Column.ts +8 -0
  155. package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +310 -0
  156. package/UI/Components/ModelTable/ColumnPreference.ts +13 -1
  157. package/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.tsx +2 -2
  158. package/UI/Components/SideOver/SideOver.tsx +5 -5
  159. package/UI/Components/StatusPage/ResourceGrid.tsx +82 -2
  160. package/UI/Components/StatusPage/ResourceList.tsx +197 -38
  161. package/UI/Components/Toggle/Toggle.tsx +9 -1
  162. package/UI/Components/Types/FieldType.ts +1 -0
  163. package/Utils/NetworkDevice/DeviceReachabilityUtil.ts +73 -1
  164. package/Utils/NetworkDiscovery/ScanNameUtil.ts +181 -0
  165. package/Utils/StatusPage/ResourceExplorer.ts +258 -0
  166. package/Utils/Telemetry/LlmMetricQuery.ts +287 -0
  167. package/build/dist/Models/AnalyticsModels/Span.js +89 -0
  168. package/build/dist/Models/AnalyticsModels/Span.js.map +1 -1
  169. package/build/dist/Models/DatabaseModels/DetectionRule.js +57 -0
  170. package/build/dist/Models/DatabaseModels/DetectionRule.js.map +1 -1
  171. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +27 -7
  172. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -1
  173. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +69 -0
  174. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  175. package/build/dist/Models/DatabaseModels/Project.js +76 -0
  176. package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
  177. package/build/dist/Models/DatabaseModels/User.js +76 -0
  178. package/build/dist/Models/DatabaseModels/User.js.map +1 -1
  179. package/build/dist/Server/API/BaseAPI.js +3 -19
  180. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  181. package/build/dist/Server/API/SlackAPI.js +0 -2
  182. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  183. package/build/dist/Server/API/TelemetryAPI.js +17 -0
  184. package/build/dist/Server/API/TelemetryAPI.js.map +1 -1
  185. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js +21 -0
  186. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789400000000-AddNameToNetworkDeviceDiscoveryScan.js.map +1 -0
  187. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js +42 -0
  188. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789500000000-AddCampaignUtmFields.js.map +1 -0
  189. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js +22 -0
  190. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789512000000-AddDetectionRuleDistinctCountColumns.js.map +1 -0
  191. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  192. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  193. package/build/dist/Server/Middleware/GzipRequestBody.js +224 -0
  194. package/build/dist/Server/Middleware/GzipRequestBody.js.map +1 -0
  195. package/build/dist/Server/Middleware/MultipartFormData.js +71 -2
  196. package/build/dist/Server/Middleware/MultipartFormData.js.map +1 -1
  197. package/build/dist/Server/Middleware/SlackAuthorization.js +58 -7
  198. package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
  199. package/build/dist/Server/Services/DetectionRuleService.js +49 -4
  200. package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
  201. package/build/dist/Server/Services/Index.js +204 -0
  202. package/build/dist/Server/Services/Index.js.map +1 -1
  203. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +50 -0
  204. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  205. package/build/dist/Server/Services/NetworkDeviceService.js +124 -0
  206. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  207. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +68 -13
  208. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  209. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js +1 -1
  210. package/build/dist/Server/Services/OnCallDutyPolicyFeedService.js.map +1 -1
  211. package/build/dist/Server/Services/ProjectService.js +25 -45
  212. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  213. package/build/dist/Server/Services/SecurityEventService.js +57 -5
  214. package/build/dist/Server/Services/SecurityEventService.js.map +1 -1
  215. package/build/dist/Server/Services/StatusPageResourceService.js +140 -0
  216. package/build/dist/Server/Services/StatusPageResourceService.js.map +1 -1
  217. package/build/dist/Server/Services/TelemetryAttributeService.js +17 -0
  218. package/build/dist/Server/Services/TelemetryAttributeService.js.map +1 -1
  219. package/build/dist/Server/Services/UserService.js +2 -12
  220. package/build/dist/Server/Services/UserService.js.map +1 -1
  221. package/build/dist/Server/Types/Markdown.js +147 -61
  222. package/build/dist/Server/Types/Markdown.js.map +1 -1
  223. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js +12 -4
  224. package/build/dist/Server/Utils/AI/Toolbox/OnCallTools.js.map +1 -1
  225. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js +12 -1
  226. package/build/dist/Server/Utils/AnalyticsDatabase/Statement.js.map +1 -1
  227. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js +246 -9
  228. package/build/dist/Server/Utils/AnalyticsDatabase/StatementGenerator.js.map +1 -1
  229. package/build/dist/Server/Utils/Attribution.js.map +1 -1
  230. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +27 -7
  231. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -1
  232. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +42 -7
  233. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
  234. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +18 -0
  235. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
  236. package/build/dist/Server/Utils/StartServer.js +12 -21
  237. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  238. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js +76 -5
  239. package/build/dist/Server/Utils/Telemetry/LlmCostBudgetEvaluator.js.map +1 -1
  240. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js +151 -0
  241. package/build/dist/Server/Utils/Telemetry/LlmMetricSpend.js.map +1 -0
  242. package/build/dist/Server/Utils/Telemetry/LlmSpan.js +24 -1
  243. package/build/dist/Server/Utils/Telemetry/LlmSpan.js.map +1 -1
  244. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js +0 -10
  245. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js.map +1 -1
  246. package/build/dist/Types/Code/YamlSyntax.js +212 -0
  247. package/build/dist/Types/Code/YamlSyntax.js.map +1 -0
  248. package/build/dist/Types/Exception/ExceptionCode.js +1 -0
  249. package/build/dist/Types/Exception/ExceptionCode.js.map +1 -1
  250. package/build/dist/Types/Exception/PayloadTooLargeException.js +8 -0
  251. package/build/dist/Types/Exception/PayloadTooLargeException.js.map +1 -0
  252. package/build/dist/Types/Marketing/Attribution.js +10 -0
  253. package/build/dist/Types/Marketing/Attribution.js.map +1 -1
  254. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +112 -51
  255. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  256. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +2 -1
  257. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -1
  258. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +9 -0
  259. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
  260. package/build/dist/Types/Telemetry/LlmConventions.js +236 -0
  261. package/build/dist/Types/Telemetry/LlmConventions.js.map +1 -1
  262. package/build/dist/Types/Telemetry/LlmMetricConventions.js +290 -0
  263. package/build/dist/Types/Telemetry/LlmMetricConventions.js.map +1 -0
  264. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js +1 -1
  265. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js.map +1 -1
  266. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js +5 -2
  267. package/build/dist/UI/Components/BulkUpdate/BulkUpdateForm.js.map +1 -1
  268. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +206 -76
  269. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  270. package/build/dist/UI/Components/CodeEditor/YamlEditor.js +201 -0
  271. package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -0
  272. package/build/dist/UI/Components/Detail/Detail.js +9 -0
  273. package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
  274. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +16 -1
  275. package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
  276. package/build/dist/UI/Components/Forms/Fields/FormField.js +14 -1
  277. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  278. package/build/dist/UI/Components/Forms/Types/Field.js.map +1 -1
  279. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js +1 -0
  280. package/build/dist/UI/Components/Forms/Types/FormFieldSchemaType.js.map +1 -1
  281. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js +2 -0
  282. package/build/dist/UI/Components/Forms/Utils/FormFieldSchemaTypeUtil.js.map +1 -1
  283. package/build/dist/UI/Components/Forms/Validation.js +27 -0
  284. package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
  285. package/build/dist/UI/Components/Input/Input.js +1 -1
  286. package/build/dist/UI/Components/Input/Input.js.map +1 -1
  287. package/build/dist/UI/Components/ModelTable/AttributeColumns.js +159 -0
  288. package/build/dist/UI/Components/ModelTable/AttributeColumns.js.map +1 -0
  289. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +179 -17
  290. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  291. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +133 -2
  292. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -1
  293. package/build/dist/UI/Components/ModelTable/ColumnPreference.js +7 -1
  294. package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -1
  295. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesModal.js +2 -2
  296. package/build/dist/UI/Components/SideOver/SideOver.js +5 -5
  297. package/build/dist/UI/Components/StatusPage/ResourceGrid.js +28 -2
  298. package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
  299. package/build/dist/UI/Components/StatusPage/ResourceList.js +87 -20
  300. package/build/dist/UI/Components/StatusPage/ResourceList.js.map +1 -1
  301. package/build/dist/UI/Components/Toggle/Toggle.js +9 -1
  302. package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
  303. package/build/dist/UI/Components/Types/FieldType.js +1 -0
  304. package/build/dist/UI/Components/Types/FieldType.js.map +1 -1
  305. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js +37 -1
  306. package/build/dist/Utils/NetworkDevice/DeviceReachabilityUtil.js.map +1 -1
  307. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js +120 -0
  308. package/build/dist/Utils/NetworkDiscovery/ScanNameUtil.js.map +1 -0
  309. package/build/dist/Utils/StatusPage/ResourceExplorer.js +171 -0
  310. package/build/dist/Utils/StatusPage/ResourceExplorer.js.map +1 -1
  311. package/build/dist/Utils/Telemetry/LlmMetricQuery.js +175 -0
  312. package/build/dist/Utils/Telemetry/LlmMetricQuery.js.map +1 -0
  313. package/jest.config.json +2 -0
  314. package/package.json +1 -1
  315. package/tsconfig.json +2 -1
  316. package/Tests/UI/Components/Toast.test.tsx +0 -197
  317. package/Tests/UI/Components/ToastStacking.test.tsx +0 -198
  318. package/UI/Components/Toast/Toast.tsx +0 -189
  319. package/UI/Components/Toast/ToastInit.tsx +0 -110
  320. package/build/dist/UI/Components/Toast/Toast.js +0 -123
  321. package/build/dist/UI/Components/Toast/Toast.js.map +0 -1
  322. package/build/dist/UI/Components/Toast/ToastInit.js +0 -53
  323. package/build/dist/UI/Components/Toast/ToastInit.js.map +0 -1
@@ -101,7 +101,7 @@ const renderOrigin: RenderOriginFunction = (
101
101
  };
102
102
 
103
103
  const GTM_SCRIPT: string = "googletagmanager.com/gtm.js";
104
- const CONSENT_DEFAULT: string = "pushConsentSignal('default', false)";
104
+ const CONSENT_DEFAULT: string = "pushConsentSignal('default', true)";
105
105
 
106
106
  describe("the shared analytics consent partial", () => {
107
107
  test("exists in Common, so every origin can reach it", () => {
@@ -166,15 +166,37 @@ for (const origin of ORIGINS) {
166
166
  expect(consentIndex).toBeLessThan(containerIndex);
167
167
  });
168
168
 
169
- test("denies ad and analytics storage until the visitor answers", () => {
169
+ /*
170
+ * Granted by default, on every origin, without asking. This is the
171
+ * deliberate posture (see the top of the partial); the assertion exists so
172
+ * that reverting to a denied default has to be a decision rather than an
173
+ * accident, and so that the four origins cannot drift apart on it.
174
+ *
175
+ * Note what this default asserts to Google: that consent WAS collected.
176
+ * That is a claim about the visitor, not merely a choice about OneUptime's
177
+ * own storage.
178
+ */
179
+ test("grants ad and analytics storage by default, without asking", () => {
170
180
  const html: string = renderOrigin(origin, true);
171
181
 
172
182
  expect(html).toContain("ad_storage");
173
183
  expect(html).toContain("ad_user_data");
174
184
  expect(html).toContain("ad_personalization");
175
185
  expect(html).toContain("analytics_storage");
176
- // `unset` is treated as denied rather than as permission-by-silence.
177
186
  expect(html).toContain(CONSENT_DEFAULT);
187
+ expect(html).not.toContain("pushConsentSignal('default', false)");
188
+ });
189
+
190
+ /*
191
+ * And no update is pushed on either answer, so "Reject all" does not send
192
+ * a denial. Without this, re-adding a single pushConsentSignal('update', …)
193
+ * in set() would quietly re-gate the Google tag while every other test
194
+ * here stayed green.
195
+ */
196
+ test("pushes no consent update when the banner is answered", () => {
197
+ const html: string = renderOrigin(origin, true);
198
+
199
+ expect(html).not.toContain("pushConsentSignal('update'");
178
200
  });
179
201
 
180
202
  test("loads no Google tag at all when analytics are switched off", () => {
@@ -235,7 +257,28 @@ describe("consent can be withdrawn", () => {
235
257
  expect(policy).not.toContain(
236
258
  "We do not use marketing cookies inside the product",
237
259
  );
238
- expect(policy).toContain("governed by the same");
239
- expect(policy).toContain("consent choice");
260
+ expect(policy).toContain(
261
+ "the same analytics and advertising tags as the rest of the Website",
262
+ );
263
+ });
264
+
265
+ /*
266
+ * And it must not promise a choice the code stopped honouring.
267
+ *
268
+ * The policy used to say the product's tags were "governed by the same
269
+ * consent choice" and that rejecting meant "they are not set in the product
270
+ * either". Measurement is no longer gated on the banner, so both sentences
271
+ * became false statements to visitors in a published policy — the kind of
272
+ * defect that is invisible in code review because the code and the prose
273
+ * live in different files.
274
+ */
275
+ test("the cookie policy does not promise a consent choice the code ignores", () => {
276
+ const policy: string = fs.readFileSync(cookiePolicyPath, "utf-8");
277
+
278
+ expect(policy).not.toContain("governed by the same consent choice");
279
+ expect(policy).not.toContain("they are not set in the product either");
280
+ expect(policy).toContain(
281
+ "regardless of the answer given on the cookie banner",
282
+ );
240
283
  });
241
284
  });
@@ -0,0 +1,396 @@
1
+ import {
2
+ YamlSyntaxCheckResult,
3
+ checkYamlSyntax,
4
+ describeYamlSyntaxError,
5
+ } from "../../../Types/Code/YamlSyntax";
6
+ import { describe, expect, test } from "@jest/globals";
7
+
8
+ /*
9
+ * checkYamlSyntax answers one question — "would a YAML parser accept this
10
+ * text?" — and is the single source of truth behind both the form-level
11
+ * validator and the YAML editor's status bar. It is pure: same string in,
12
+ * same verdict out, no time, network or randomness.
13
+ *
14
+ * Its contract deliberately mirrors checkJSONSyntax's: permissive about
15
+ * anything it cannot decide (non-strings, empty boxes, handlebars loops),
16
+ * definite about anything it can.
17
+ */
18
+
19
+ const VALID_SIGMA_RULE: string = `title: Failed logon burst
20
+ logsource:
21
+ category: authentication
22
+ detection:
23
+ selection:
24
+ className: Authentication
25
+ statusName: Failure
26
+ condition: selection
27
+ level: high
28
+ `;
29
+
30
+ describe("checkYamlSyntax — accepts what a YAML parser accepts", () => {
31
+ test("a real Sigma rule", () => {
32
+ const result: YamlSyntaxCheckResult = checkYamlSyntax(VALID_SIGMA_RULE);
33
+
34
+ expect(result.isValid).toBe(true);
35
+ expect(result.wasSkipped).toBe(false);
36
+ expect(result.errorMessage).toBeNull();
37
+ expect(result.line).toBeNull();
38
+ expect(result.column).toBeNull();
39
+ });
40
+
41
+ test("a flat mapping", () => {
42
+ expect(checkYamlSyntax("a: 1\nb: two\n").isValid).toBe(true);
43
+ });
44
+
45
+ test("a sequence", () => {
46
+ expect(checkYamlSyntax("- one\n- two\n- three\n").isValid).toBe(true);
47
+ });
48
+
49
+ test("flow style, which is also legal JSON", () => {
50
+ expect(checkYamlSyntax('{"a": 1, "b": [1, 2]}').isValid).toBe(true);
51
+ });
52
+
53
+ test("a bare scalar — a lone word is a valid YAML document", () => {
54
+ expect(checkYamlSyntax("hello").isValid).toBe(true);
55
+ });
56
+
57
+ test("comments, which the editor must never strip", () => {
58
+ expect(
59
+ checkYamlSyntax("# what this rule catches\ntitle: Something\n").isValid,
60
+ ).toBe(true);
61
+ });
62
+
63
+ test("anchors and aliases", () => {
64
+ expect(
65
+ checkYamlSyntax("base: &base\n a: 1\nderived:\n <<: *base\n").isValid,
66
+ ).toBe(true);
67
+ });
68
+
69
+ test("a block scalar", () => {
70
+ expect(
71
+ checkYamlSyntax("description: |\n line one\n line two\n").isValid,
72
+ ).toBe(true);
73
+ });
74
+
75
+ /*
76
+ * A YAML stream can hold several documents separated by `---`. load() throws
77
+ * on the second one, loadAll() does not — this pins that the implementation
78
+ * uses loadAll.
79
+ */
80
+ test("a multi-document stream", () => {
81
+ expect(checkYamlSyntax("---\na: 1\n---\nb: 2\n").isValid).toBe(true);
82
+ });
83
+
84
+ test("a document that is only a comment", () => {
85
+ expect(checkYamlSyntax("# nothing but a note\n").isValid).toBe(true);
86
+ });
87
+ });
88
+
89
+ describe("checkYamlSyntax — catches the real mistakes", () => {
90
+ test("an unclosed flow sequence", () => {
91
+ const result: YamlSyntaxCheckResult = checkYamlSyntax("title: [unclosed");
92
+
93
+ expect(result.isValid).toBe(false);
94
+ expect(result.wasSkipped).toBe(false);
95
+ expect(result.errorMessage).toBeTruthy();
96
+ });
97
+
98
+ test("an unclosed flow mapping", () => {
99
+ expect(checkYamlSyntax("detection: {selection: 1").isValid).toBe(false);
100
+ });
101
+
102
+ test("a tab used for indentation — illegal in YAML, invisible on screen", () => {
103
+ const result: YamlSyntaxCheckResult = checkYamlSyntax(
104
+ "detection:\n\tselection: 1\n",
105
+ );
106
+
107
+ expect(result.isValid).toBe(false);
108
+ });
109
+
110
+ test("two mapping keys at odds about their indentation", () => {
111
+ const result: YamlSyntaxCheckResult = checkYamlSyntax(
112
+ "detection:\n selection: 1\n condition: selection\n",
113
+ );
114
+
115
+ expect(result.isValid).toBe(false);
116
+ });
117
+
118
+ test("a duplicated mapping key", () => {
119
+ expect(checkYamlSyntax("title: one\ntitle: two\n").isValid).toBe(false);
120
+ });
121
+
122
+ test("an unclosed quote", () => {
123
+ expect(checkYamlSyntax('title: "never closed\n').isValid).toBe(false);
124
+ });
125
+ });
126
+
127
+ describe("checkYamlSyntax — reports where the failure is", () => {
128
+ /*
129
+ * The line and column are the whole point of the message: the editor turns
130
+ * the gutter on for YAML precisely so the reader can go there.
131
+ */
132
+ test("a 1-based line and column, not js-yaml's 0-based mark", () => {
133
+ const result: YamlSyntaxCheckResult = checkYamlSyntax(
134
+ "title: fine\ndetection:\n selection: 1\n condition: selection\n",
135
+ );
136
+
137
+ expect(result.isValid).toBe(false);
138
+ expect(result.line).not.toBeNull();
139
+ expect(result.line).toBeGreaterThanOrEqual(1);
140
+ expect(result.column).not.toBeNull();
141
+ expect(result.column).toBeGreaterThanOrEqual(1);
142
+ });
143
+
144
+ test("a single-line reason, not js-yaml's multi-line source excerpt", () => {
145
+ const result: YamlSyntaxCheckResult = checkYamlSyntax("title: [unclosed");
146
+
147
+ expect(result.errorMessage).not.toContain("\n");
148
+ });
149
+
150
+ test("the reason does not repeat the coordinates the caller adds", () => {
151
+ const result: YamlSyntaxCheckResult = checkYamlSyntax(
152
+ "detection:\n selection: 1\n condition: selection\n",
153
+ );
154
+
155
+ // js-yaml's `message` ends with "(3:4)"; its `reason` does not.
156
+ expect(result.errorMessage).not.toMatch(/\(\d+:\d+\)/);
157
+ });
158
+ });
159
+
160
+ describe("checkYamlSyntax — declines to judge what it cannot know", () => {
161
+ /*
162
+ * Every one of these is reported valid AND flagged as skipped, so a caller
163
+ * that wants to explain itself can tell "passed" from "not checked".
164
+ */
165
+ test("a non-string, because nothing was typed", () => {
166
+ for (const value of [undefined, null, 42, true, { a: 1 }, ["a"]]) {
167
+ const result: YamlSyntaxCheckResult = checkYamlSyntax(value);
168
+
169
+ expect(result.isValid).toBe(true);
170
+ expect(result.wasSkipped).toBe(true);
171
+ }
172
+ });
173
+
174
+ test("empty and whitespace-only, which is the required check's job", () => {
175
+ for (const value of ["", " ", "\n\n", "\t"]) {
176
+ const result: YamlSyntaxCheckResult = checkYamlSyntax(value);
177
+
178
+ expect(result.isValid).toBe(true);
179
+ expect(result.wasSkipped).toBe(true);
180
+ }
181
+ });
182
+
183
+ test("a handlebars loop, whose shape is only known at run time", () => {
184
+ const result: YamlSyntaxCheckResult = checkYamlSyntax(
185
+ "items:\n{{#each local.variables.hosts}}\n - {{this}}\n{{/each}}\n",
186
+ );
187
+
188
+ expect(result.isValid).toBe(true);
189
+ expect(result.wasSkipped).toBe(true);
190
+ });
191
+ });
192
+
193
+ describe("checkYamlSyntax — tolerates handlebars the way the JSON check does", () => {
194
+ test("a template standing in for a value", () => {
195
+ expect(
196
+ checkYamlSyntax("threshold: {{local.variables.count}}").isValid,
197
+ ).toBe(true);
198
+ });
199
+
200
+ test("a template inside a quoted string", () => {
201
+ expect(
202
+ checkYamlSyntax('auth: "Bearer {{local.variables.token}}"').isValid,
203
+ ).toBe(true);
204
+ });
205
+
206
+ test("a whole-field template", () => {
207
+ expect(
208
+ checkYamlSyntax("{{local.components.a.returnValues.body}}").isValid,
209
+ ).toBe(true);
210
+ });
211
+
212
+ test("masking does not paper over a genuine error elsewhere", () => {
213
+ expect(
214
+ checkYamlSyntax("threshold: {{local.variables.count}}\nbad: [unclosed")
215
+ .isValid,
216
+ ).toBe(false);
217
+ });
218
+ });
219
+
220
+ describe("checkYamlSyntax — purity", () => {
221
+ test("the same input yields the same verdict every time", () => {
222
+ for (const value of [VALID_SIGMA_RULE, "title: [unclosed", "", "a: 1"]) {
223
+ expect(checkYamlSyntax(value)).toEqual(checkYamlSyntax(value));
224
+ }
225
+ });
226
+
227
+ test("does not mutate or consume its input", () => {
228
+ const original: string = VALID_SIGMA_RULE;
229
+
230
+ checkYamlSyntax(original);
231
+
232
+ expect(original).toBe(VALID_SIGMA_RULE);
233
+ });
234
+ });
235
+
236
+ describe("describeYamlSyntaxError — one readable sentence", () => {
237
+ test("reason, line and column when all three are known", () => {
238
+ expect(
239
+ describeYamlSyntaxError({
240
+ isValid: false,
241
+ errorMessage: "bad indentation of a mapping entry",
242
+ wasSkipped: false,
243
+ line: 4,
244
+ column: 3,
245
+ }),
246
+ ).toBe("bad indentation of a mapping entry (line 4, column 3)");
247
+ });
248
+
249
+ test("drops the column when the parser did not report one", () => {
250
+ expect(
251
+ describeYamlSyntaxError({
252
+ isValid: false,
253
+ errorMessage: "unexpected end of the stream",
254
+ wasSkipped: false,
255
+ line: 9,
256
+ column: null,
257
+ }),
258
+ ).toBe("unexpected end of the stream (line 9)");
259
+ });
260
+
261
+ test("the bare reason when there is no position at all", () => {
262
+ expect(
263
+ describeYamlSyntaxError({
264
+ isValid: false,
265
+ errorMessage: "something went wrong",
266
+ wasSkipped: false,
267
+ line: null,
268
+ column: null,
269
+ }),
270
+ ).toBe("something went wrong");
271
+ });
272
+
273
+ test("never renders an empty sentence", () => {
274
+ expect(
275
+ describeYamlSyntaxError({
276
+ isValid: false,
277
+ errorMessage: null,
278
+ wasSkipped: false,
279
+ line: null,
280
+ column: null,
281
+ }),
282
+ ).toBe("Invalid YAML.");
283
+ });
284
+
285
+ test("describes a real parse failure end to end", () => {
286
+ const result: YamlSyntaxCheckResult = checkYamlSyntax(
287
+ "detection:\n selection: 1\n condition: selection\n",
288
+ );
289
+
290
+ const sentence: string = describeYamlSyntaxError(result);
291
+
292
+ expect(sentence).toContain("line ");
293
+ expect(sentence).not.toContain("\n");
294
+ });
295
+ });
296
+
297
+ /*
298
+ * Tabs in indentation.
299
+ *
300
+ * js-yaml ACCEPTS tab-indented YAML rather than rejecting it, and quietly
301
+ * restructures the document: `detection:\n\tselection: 1` yields
302
+ * `{detection: null, selection: 1}` — a sibling where the author wrote a
303
+ * child. So checkYamlSyntax finds these itself, and the risk moves from
304
+ * missing them to over-reporting: a tab is only illegal in INDENTATION, and
305
+ * every "allows" case below is legal YAML that js-yaml parses. Flagging one of
306
+ * them would block Save on a working document, which is the failure this
307
+ * module's permissiveness exists to prevent.
308
+ */
309
+ describe("checkYamlSyntax — tabs used for indentation", () => {
310
+ test("reports the line and column of the tab", () => {
311
+ const result: YamlSyntaxCheckResult = checkYamlSyntax(
312
+ "detection:\n\tselection: 1\n",
313
+ );
314
+
315
+ expect(result.isValid).toBe(false);
316
+ expect(result.wasSkipped).toBe(false);
317
+ expect(result.line).toBe(2);
318
+ expect(result.column).toBe(1);
319
+ expect(describeYamlSyntaxError(result)).toContain("line 2");
320
+ });
321
+
322
+ test.each([
323
+ ["a tab indenting a sequence entry", "a:\n\t- 1\n", 2],
324
+ ["spaces followed by a tab", "a:\n \tb: 1\n", 2],
325
+ [
326
+ "a tab on a line after a block scalar closes",
327
+ "a: |\n body\nb:\n\tc: 1\n",
328
+ 4,
329
+ ],
330
+ ["a CRLF document", "a:\r\n\tb: 1\r\n", 2],
331
+ [
332
+ "a tab several levels into the document",
333
+ "a:\n b:\n c: 1\n\td: 2\n",
334
+ 4,
335
+ ],
336
+ ])("rejects %s", (_label: string, document: string, line: number) => {
337
+ const result: YamlSyntaxCheckResult = checkYamlSyntax(document);
338
+
339
+ expect(result.isValid).toBe(false);
340
+ expect(result.line).toBe(line);
341
+ });
342
+
343
+ /*
344
+ * Each of these parses under js-yaml. Verified case by case rather than
345
+ * assumed — a tab is ordinary content inside a scalar, and legal separation
346
+ * whitespace inside a flow collection.
347
+ */
348
+ test.each([
349
+ ["a tab inside block scalar content", "a: |\n line\twith tab\n"],
350
+ [
351
+ "a block scalar line that starts with a tab",
352
+ "a: |\n first\n \tindented more\n",
353
+ ],
354
+ [
355
+ "a block scalar with an explicit indent indicator",
356
+ "a: |2\n \tcontent\n",
357
+ ],
358
+ ["a block scalar with chomping indicators", "a: |-\n \tx\nb: >+\n \ty\n"],
359
+ [
360
+ "a block scalar containing a blank line",
361
+ "a: |\n one\n\n \ttwo\nb: 2\n",
362
+ ],
363
+ ["a block scalar inside a sequence", "- |\n \tx\n- 2\n"],
364
+ [
365
+ "YAML embedded in a block scalar, as a ConfigMap does",
366
+ "data:\n app.yaml: |\n outer:\n \tinner: 1\n",
367
+ ],
368
+ ["a block scalar line shaped like a mapping key", "a: |\n x:\n \ty: 1\n"],
369
+ ["a double-quoted scalar continued on a tabbed line", 'a: "one\n\ttwo"\n'],
370
+ ["a single-quoted scalar continued on a tabbed line", "a: 'one\n\ttwo'\n"],
371
+ [
372
+ "a quoted continuation that looks like a mapping key",
373
+ 'a: "one\n\ttwo: three"\n',
374
+ ],
375
+ ["a flow mapping spanning lines", "a: {\n\tb: 1 }\n"],
376
+ ["a tab inside a quoted value", 'a: "x\ty"\n'],
377
+ ["a tab inside a comment", "a: 1 #\tcomment\n"],
378
+ ["a tab inside folded scalar content", "a: >\n text\there\n"],
379
+ ])("allows %s", (_label: string, document: string) => {
380
+ expect(checkYamlSyntax(document).isValid).toBe(true);
381
+ });
382
+
383
+ /*
384
+ * The apostrophe in `it's` is not an opening quote. Reading it as one would
385
+ * leave a scalar "open" for the rest of the document and silence the check
386
+ * from that line on — a miss rather than a false positive, but a total one.
387
+ */
388
+ test("an apostrophe in a plain scalar does not blind the rest of the document", () => {
389
+ const result: YamlSyntaxCheckResult = checkYamlSyntax(
390
+ "a: it's fine\nb:\n\tc: 1\n",
391
+ );
392
+
393
+ expect(result.isValid).toBe(false);
394
+ expect(result.line).toBe(3);
395
+ });
396
+ });