@oneuptime/common 12.0.6 → 12.0.7
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.
- package/Models/DatabaseModels/AIInsight.ts +1 -1
- package/Models/DatabaseModels/DatabaseBaseModel/FileModel.ts +2 -3
- package/Models/DatabaseModels/DeletedProject.ts +595 -0
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/Monitor.ts +111 -0
- package/Models/DatabaseModels/Project.ts +3 -3
- package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +19 -1
- package/Server/API/FileAPI.ts +15 -2
- package/Server/API/MicrosoftTeamsAPI.ts +6 -1
- package/Server/API/ProjectAPI.ts +214 -0
- package/Server/API/StatusPageAPI.ts +39 -6
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.ts +50 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.ts +67 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.ts +39 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Services/AIAgentService.ts +20 -0
- package/Server/Services/DashboardDomainService.ts +73 -28
- package/Server/Services/DatabaseService.ts +1 -0
- package/Server/Services/DeletedProjectService.ts +138 -0
- package/Server/Services/FileService.ts +61 -0
- package/Server/Services/IncidentEpisodePublicNoteService.ts +18 -0
- package/Server/Services/IncidentPublicNoteService.ts +18 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/MonitorService.ts +311 -0
- package/Server/Services/ProbeService.ts +20 -0
- package/Server/Services/ProjectService.ts +297 -1
- package/Server/Services/PushNotificationService.ts +71 -0
- package/Server/Services/ScheduledMaintenancePublicNoteService.ts +18 -0
- package/Server/Services/StatusPageAnnouncementService.ts +53 -0
- package/Server/Services/StatusPageDomainService.ts +73 -28
- package/Server/Services/TeamMemberService.ts +117 -12
- package/Server/Services/TelemetryIngestionKeyService.ts +1 -0
- package/Server/Services/UserWebhookService.ts +34 -109
- package/Server/Services/WorkspaceNotificationRuleService.ts +69 -0
- package/Server/Services/WorkspaceProjectAuthTokenService.ts +37 -1
- package/Server/Types/Database/DeleteById.ts +2 -0
- package/Server/Types/Database/DeleteOneBy.ts +6 -0
- package/Server/Types/Domain.ts +41 -0
- package/Server/Types/Workflow/Components/API/Delete.ts +2 -1
- package/Server/Types/Workflow/Components/API/Get.ts +2 -1
- package/Server/Types/Workflow/Components/API/Patch.ts +2 -1
- package/Server/Types/Workflow/Components/API/Post.ts +2 -1
- package/Server/Types/Workflow/Components/API/Put.ts +2 -1
- package/Server/Types/Workflow/Components/API/Utils.ts +41 -2
- package/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.ts +25 -19
- package/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.ts +6 -5
- package/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.ts +32 -14
- package/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.ts +31 -13
- package/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.ts +29 -20
- package/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.ts +28 -21
- package/Server/Types/Workflow/Components/BaseModel/LogComponentError.ts +89 -0
- package/Server/Types/Workflow/Components/BaseModel/ModelArguments.ts +208 -0
- package/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.ts +11 -0
- package/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.ts +41 -18
- package/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.ts +45 -19
- package/Server/Types/Workflow/Components/Discord/SendMessageToChannel.ts +16 -9
- package/Server/Types/Workflow/Components/IncomingWebhookUtils.ts +66 -0
- package/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.ts +15 -9
- package/Server/Types/Workflow/Components/Slack/SendMessageToChannel.ts +17 -0
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
- package/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.ts +171 -0
- package/Server/Utils/AI/SRE/FixFromIncidentTaskTrigger.ts +3 -3
- package/Server/Utils/AI/SRE/Insights/FixRouting.ts +3 -2
- package/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.ts +1 -1
- package/Server/Utils/AI/Toolbox/CodeWriteTools.ts +6 -6
- package/Server/Utils/CodeRepository/GitHub/GitHub.ts +43 -5
- package/Server/Utils/DataSource/EgressGuard.ts +176 -16
- package/Server/Utils/DataSource/HttpFetch.ts +6 -45
- package/Server/Utils/Execute.ts +8 -0
- package/Server/Utils/InlineImageAccessTokenSync.ts +23 -0
- package/Server/Utils/LLM/LLMService.ts +57 -12
- package/Server/Utils/Monitor/MonitorAlert.ts +40 -0
- package/Server/Utils/Monitor/MonitorDependencySuppression.ts +192 -0
- package/Server/Utils/Monitor/MonitorIncident.ts +40 -0
- package/Server/Utils/Monitor/MonitorResource.ts +36 -0
- package/Server/Utils/Response.ts +142 -6
- package/Server/Utils/SSRFProtection.ts +273 -60
- package/Server/Utils/StartServer.ts +8 -0
- package/Server/Utils/VM/VMRunner.ts +88 -1
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +555 -49
- package/Server/Utils/Workspace/Slack/Slack.ts +25 -2
- package/Server/Utils/Workspace/WorkspaceBase.ts +6 -0
- package/Tests/App/Dashboard/DangerZone.test.tsx +334 -0
- package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +539 -0
- package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +678 -0
- package/Tests/App/Dashboard/DashboardVariablesDiscard.test.tsx +706 -0
- package/Tests/App/Dashboard/DashboardVariablesModal.test.tsx +508 -0
- package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +470 -0
- package/Tests/App/StatusPage/StatusPageDetailPagesNotFound.test.tsx +308 -0
- package/Tests/Models/DatabaseModels/DeletedProjectModel.test.ts +251 -0
- package/Tests/Models/DatabaseModels/SavedViewJSONColumnTuples.test.ts +115 -0
- package/Tests/Server/API/FileAPIAccessControl.test.ts +316 -0
- package/Tests/Server/API/ProjectAPI.test.ts +299 -1
- package/Tests/Server/API/ProjectAPIAdjustBalance.test.ts +459 -0
- package/Tests/Server/API/ProjectAPIAdjustBalanceBillingDisabled.test.ts +177 -0
- package/Tests/Server/Services/DatabaseServiceDeletionReason.test.ts +123 -0
- package/Tests/Server/Services/DeletedProjectService.test.ts +415 -0
- package/Tests/Server/Services/DeletedProjectServiceSelfHosted.test.ts +70 -0
- package/Tests/Server/Services/DomainSubdomainHooks.test.ts +94 -0
- package/Tests/Server/Services/FileIsPublicBooleanMigration.test.ts +244 -0
- package/Tests/Server/Services/FileServiceMimeType.test.ts +89 -0
- package/Tests/Server/Services/MonitorServiceDependencyValidation.test.ts +702 -0
- package/Tests/Server/Services/ProjectServiceAdjustBalance.test.ts +615 -0
- package/Tests/Server/Services/ProjectServiceDeleteAudit.test.ts +406 -0
- package/Tests/Server/Services/PublishTimeImageVisibility.test.ts +450 -0
- package/Tests/Server/Services/TeamMemberAutoAcceptInvitation.test.ts +669 -0
- package/Tests/Server/Services/UserWebhookSSRF.test.ts +174 -0
- package/Tests/Server/Services/WebPushEndpointAllowlist.test.ts +133 -0
- package/Tests/Server/Services/WorkspaceProjectAuthTokenRepoint.test.ts +618 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +26 -1
- package/Tests/Server/Types/Workflow/Components/ApiComponentSsrf.test.ts +215 -0
- package/Tests/Server/Types/Workflow/Components/BaseModelDatabaseComponents.test.ts +742 -0
- package/Tests/Server/Types/Workflow/Components/ChatWebhookComponents.test.ts +256 -0
- package/Tests/Server/Types/Workflow/Components/ModelArguments.test.ts +371 -0
- package/Tests/Server/Utils/AI/CodeAgentCommandGuard.test.ts +204 -0
- package/Tests/Server/Utils/AI/CodeAgentWriteLimits.test.ts +213 -0
- package/Tests/Server/Utils/AI/CodeWriteTools.test.ts +52 -5
- package/Tests/Server/Utils/AI/LLMServiceBaseUrl.test.ts +3 -0
- package/Tests/Server/Utils/AI/LLMServiceEgressGuard.test.ts +315 -0
- package/Tests/Server/Utils/AI/LLMServiceModelCompatibility.test.ts +3 -0
- package/Tests/Server/Utils/AI/LLMServiceRequestPolicy.test.ts +17 -5
- package/Tests/Server/Utils/AI/LLMServiceToolCalling.test.ts +14 -1
- package/Tests/Server/Utils/AI/ObservabilityChatPrompt.test.ts +35 -0
- package/Tests/Server/Utils/AI/StubLLMEgressGuard.ts +25 -0
- package/Tests/Server/Utils/Dashboard/PublicDashboardResourceListPolicy.test.ts +62 -7
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +69 -0
- package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +330 -0
- package/Tests/Server/Utils/GitHubCreatePullRequestWithToken.test.ts +393 -0
- package/Tests/Server/Utils/InlineImageAccessTokenSync.test.ts +202 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppression.test.ts +811 -0
- package/Tests/Server/Utils/Monitor/MonitorDependencySuppressionCreatorSkip.test.ts +604 -0
- package/Tests/Server/Utils/ResponseSendFileResponse.test.ts +192 -0
- package/Tests/Server/Utils/SSRFProtectionBypasses.test.ts +406 -0
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +194 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelSend.test.ts +1169 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChannelsList.test.ts +2 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsTeamInstalls.test.ts +1605 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsTenantResolution.test.ts +1218 -0
- package/Tests/Types/AI/AIChatMessageStatus.test.ts +79 -0
- package/Tests/Types/AI/AIInsightStatus.test.ts +40 -0
- package/Tests/Types/API/HostnameAuthorityParsing.test.ts +157 -0
- package/Tests/Types/Dashboard/DashboardTemplateInvariants.test.ts +27 -0
- package/Tests/Types/DataSource/DataSourceLimits.test.ts +71 -0
- package/Tests/Types/DataSource/DataSourceType.test.ts +181 -0
- package/Tests/Types/DomainSubdomainValidation.test.ts +90 -0
- package/Tests/Types/JSONFunctions.test.ts +252 -1
- package/Tests/Types/Monitor/SnmpMonitor/SnmpAuthProtocol.test.ts +61 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpPrivProtocol.test.ts +62 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpSecurityLevel.test.ts +68 -0
- package/Tests/Types/Monitor/SnmpMonitor/SnmpVersion.test.ts +51 -0
- package/Tests/UI/Components/404.test.tsx +1 -1
- package/Tests/UI/Components/Alert.test.tsx +1 -1
- package/Tests/UI/Components/Badge.test.tsx +1 -1
- package/Tests/UI/Components/BasicForm.test.tsx +39 -10
- package/Tests/UI/Components/Button.test.tsx +1 -1
- package/Tests/UI/Components/Card.test.tsx +1 -1
- package/Tests/UI/Components/Charts/AxisTickColor.test.tsx +1 -1
- package/Tests/UI/Components/ColorViewer.test.tsx +1 -1
- package/Tests/UI/Components/ComponentsModal.test.tsx +7 -1
- package/Tests/UI/Components/DictionaryOfStrings.test.tsx +1 -1
- package/Tests/UI/Components/Dropdown.test.tsx +1 -1
- package/Tests/UI/Components/FilePicker.test.tsx +1 -1
- package/Tests/UI/Components/HiddenText.test.tsx +1 -1
- package/Tests/UI/Components/Input.test.tsx +1 -1
- package/Tests/UI/Components/Loader.test.tsx +1 -1
- package/Tests/UI/Components/LogTimeRangePicker.test.tsx +1 -1
- package/Tests/UI/Components/MasterPage.test.tsx +1 -1
- package/Tests/UI/Components/ModalPortalDismissal.test.tsx +489 -0
- package/Tests/UI/Components/ModelDelete.test.tsx +214 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkSelectAll.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableUrlState.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1 -1
- package/Tests/UI/Components/NavBar.test.tsx +1 -1
- package/Tests/UI/Components/OperatorSelectorKeyboard.test.tsx +1 -1
- package/Tests/UI/Components/Pagination.test.tsx +1 -1
- package/Tests/UI/Components/Pill.test.tsx +1 -1
- package/Tests/UI/Components/Probe.test.tsx +1 -1
- package/Tests/UI/Components/ProgressBar.test.tsx +1 -1
- package/Tests/UI/Components/RadioButtons.test.tsx +1 -1
- package/Tests/UI/Components/SideMenuItem.test.tsx +1 -1
- package/Tests/UI/Components/SideOver.test.tsx +500 -6
- package/Tests/UI/Components/Tabs.test.tsx +1 -1
- package/Tests/UI/Components/TelemetrySearchBar.test.tsx +1 -1
- package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +1 -1
- package/Tests/UI/Components/TextArea.test.tsx +1 -1
- package/Tests/UI/Components/Toast.test.tsx +1 -1
- package/Tests/UI/Components/Toggle.test.tsx +1 -1
- package/Tests/UI/Components/TopSection.test.tsx +1 -1
- package/Tests/UI/Components/UseLiveLogsRefresh.test.tsx +1 -1
- package/Tests/UI/Rum/ReplayScrubber.test.tsx +1 -1
- package/Tests/UI/Rum/ReplayStage.test.tsx +1 -1
- package/Tests/UI/Telemetry/TelemetrySnapshotWindowAlert.test.tsx +1 -1
- package/Tests/UI/Utils/LocalStorageArrayRoundTrip.test.ts +72 -0
- package/Tests/Utils/Dashboard/HtmlWidgetDocument.test.ts +19 -2
- package/Tests/Utils/Dashboard/ModelQueryVariableInterpolation.test.ts +44 -0
- package/Tests/Utils/Dashboard/VariableInterpolation.test.ts +288 -5
- package/Tests/Utils/Dashboard/VariableUrlState.test.ts +42 -0
- package/Tests/Utils/DataSource/DataSourceQueryText.test.ts +27 -0
- package/Tests/Utils/LegacySerializedArray.test.ts +139 -0
- package/Tests/Utils/Monitor/MonitorDependencyRule.test.ts +190 -0
- package/Tests/Utils/Realtime.test.ts +78 -0
- package/Tests/Utils/Telemetry/SavedViewFilters.test.ts +246 -0
- package/Tests/__mocks__/i18next-browser-languagedetector.js +21 -0
- package/Types/AI/FixPullRequestCiStatus.ts +1 -1
- package/Types/AI/FixVerificationStatus.ts +2 -2
- package/Types/API/Hostname.ts +92 -4
- package/Types/API/URL.ts +43 -25
- package/Types/Billing/BalanceAdjustmentType.ts +14 -0
- package/Types/Billing/ProjectBalanceType.ts +13 -0
- package/Types/Domain.ts +26 -0
- package/Types/File/MimeType.ts +11 -0
- package/Types/JSONFunctions.ts +15 -0
- package/Types/Telemetry/TelemetrySavedViewState.ts +9 -1
- package/Types/Workflow/Components/BaseModel.ts +92 -28
- package/Typings/Index.d.ts +12 -0
- package/UI/Components/GanttChart/ChartContainer.tsx +4 -3
- package/UI/Components/Modal/ConfirmModal.tsx +10 -5
- package/UI/Components/Modal/Modal.tsx +27 -47
- package/UI/Components/ModelDelete/ModelDelete.tsx +23 -6
- package/UI/Components/SideOver/SideOver.tsx +195 -68
- package/UI/Utils/PageScrollLock.ts +66 -0
- package/Utils/Dashboard/HtmlWidgetDocument.ts +4 -2
- package/Utils/Dashboard/VariableInterpolation.ts +19 -1
- package/Utils/LegacySerializedArray.ts +60 -0
- package/Utils/Monitor/MonitorDependencyRule.ts +88 -0
- package/Utils/Telemetry/SavedViewFilters.ts +88 -0
- package/build/dist/Models/DatabaseModels/AIInsight.js +1 -1
- package/build/dist/Models/DatabaseModels/AIInsight.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js +2 -3
- package/build/dist/Models/DatabaseModels/DatabaseBaseModel/FileModel.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DeletedProject.js +640 -0
- package/build/dist/Models/DatabaseModels/DeletedProject.js.map +1 -0
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Monitor.js +106 -0
- package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +3 -3
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
- package/build/dist/Server/API/FileAPI.js +14 -2
- package/build/dist/Server/API/FileAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +6 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/ProjectAPI.js +157 -4
- package/build/dist/Server/API/ProjectAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +27 -3
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786446545142-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786449497966-AddMonitorDependency.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1786461136170-AddDeletedProjectTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AIAgentService.js +17 -0
- package/build/dist/Server/Services/AIAgentService.js.map +1 -1
- package/build/dist/Server/Services/DashboardDomainService.js +55 -18
- package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +1 -0
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DeletedProjectService.js +124 -0
- package/build/dist/Server/Services/DeletedProjectService.js.map +1 -0
- package/build/dist/Server/Services/FileService.js +52 -0
- package/build/dist/Server/Services/FileService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +10 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js +10 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +232 -0
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/ProbeService.js +17 -0
- package/build/dist/Server/Services/ProbeService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +228 -6
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/PushNotificationService.js +56 -0
- package/build/dist/Server/Services/PushNotificationService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +10 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageAnnouncementService.js +54 -0
- package/build/dist/Server/Services/StatusPageAnnouncementService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageDomainService.js +55 -18
- package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +97 -6
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js +1 -0
- package/build/dist/Server/Services/TelemetryIngestionKeyService.js.map +1 -1
- package/build/dist/Server/Services/UserWebhookService.js +31 -87
- package/build/dist/Server/Services/UserWebhookService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +65 -0
- package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +23 -0
- package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
- package/build/dist/Server/Types/Domain.js +37 -0
- package/build/dist/Server/Types/Domain.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js +2 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js +35 -2
- package/build/dist/Server/Types/Workflow/Components/API/Utils.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js +15 -11
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js +2 -3
- package/build/dist/Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js +21 -10
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js +21 -10
- package/build/dist/Server/Types/Workflow/Components/BaseModel/DeleteOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js +18 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js +18 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/FindOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js +43 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/LogComponentError.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js +116 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/ModelArguments.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js +7 -0
- package/build/dist/Server/Types/Workflow/Components/BaseModel/OnTriggerBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js +24 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateManyBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js +27 -13
- package/build/dist/Server/Types/Workflow/Components/BaseModel/UpdateOneBaseModel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js +14 -6
- package/build/dist/Server/Types/Workflow/Components/Discord/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js +42 -0
- package/build/dist/Server/Types/Workflow/Components/IncomingWebhookUtils.js.map +1 -0
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js +15 -6
- package/build/dist/Server/Types/Workflow/Components/MicrosoftTeams/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js +10 -2
- package/build/dist/Server/Types/Workflow/Components/Slack/SendMessageToChannel.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js +141 -0
- package/build/dist/Server/Utils/AI/CodeFix/CodeAgentWorkspaceGuard.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/Insights/FixRouting.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/TelemetryImprovementTaskTrigger.js +1 -1
- package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js +6 -6
- package/build/dist/Server/Utils/AI/Toolbox/CodeWriteTools.js.map +1 -1
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js +39 -5
- package/build/dist/Server/Utils/CodeRepository/GitHub/GitHub.js.map +1 -1
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +94 -10
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
- package/build/dist/Server/Utils/DataSource/HttpFetch.js +1 -19
- package/build/dist/Server/Utils/DataSource/HttpFetch.js.map +1 -1
- package/build/dist/Server/Utils/Execute.js +2 -2
- package/build/dist/Server/Utils/Execute.js.map +1 -1
- package/build/dist/Server/Utils/InlineImageAccessTokenSync.js +13 -0
- package/build/dist/Server/Utils/InlineImageAccessTokenSync.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +43 -12
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +44 -24
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js +158 -0
- package/build/dist/Server/Utils/Monitor/MonitorDependencySuppression.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +50 -30
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorResource.js +32 -0
- package/build/dist/Server/Utils/Monitor/MonitorResource.js.map +1 -1
- package/build/dist/Server/Utils/Response.js +112 -5
- package/build/dist/Server/Utils/Response.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +219 -53
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +7 -0
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +73 -1
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +445 -43
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js +18 -1
- package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
- package/build/dist/Types/AI/FixPullRequestCiStatus.js +1 -1
- package/build/dist/Types/AI/FixVerificationStatus.js +2 -2
- package/build/dist/Types/API/Hostname.js +73 -4
- package/build/dist/Types/API/Hostname.js.map +1 -1
- package/build/dist/Types/API/URL.js +42 -24
- package/build/dist/Types/API/URL.js.map +1 -1
- package/build/dist/Types/Billing/BalanceAdjustmentType.js +15 -0
- package/build/dist/Types/Billing/BalanceAdjustmentType.js.map +1 -0
- package/build/dist/Types/Billing/ProjectBalanceType.js +14 -0
- package/build/dist/Types/Billing/ProjectBalanceType.js.map +1 -0
- package/build/dist/Types/Domain.js +22 -0
- package/build/dist/Types/Domain.js.map +1 -1
- package/build/dist/Types/File/MimeType.js +11 -0
- package/build/dist/Types/File/MimeType.js.map +1 -1
- package/build/dist/Types/JSONFunctions.js +14 -0
- package/build/dist/Types/JSONFunctions.js.map +1 -1
- package/build/dist/Types/Workflow/Components/BaseModel.js +83 -28
- package/build/dist/Types/Workflow/Components/BaseModel.js.map +1 -1
- package/build/dist/UI/Components/GanttChart/ChartContainer.js +4 -3
- package/build/dist/UI/Components/GanttChart/ChartContainer.js.map +1 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js +3 -1
- package/build/dist/UI/Components/Modal/ConfirmModal.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +24 -34
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/ModelDelete/ModelDelete.js +11 -6
- package/build/dist/UI/Components/ModelDelete/ModelDelete.js.map +1 -1
- package/build/dist/UI/Components/SideOver/SideOver.js +105 -30
- package/build/dist/UI/Components/SideOver/SideOver.js.map +1 -1
- package/build/dist/UI/Utils/PageScrollLock.js +52 -0
- package/build/dist/UI/Utils/PageScrollLock.js.map +1 -0
- package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js +4 -2
- package/build/dist/Utils/Dashboard/HtmlWidgetDocument.js.map +1 -1
- package/build/dist/Utils/Dashboard/VariableInterpolation.js +19 -1
- package/build/dist/Utils/Dashboard/VariableInterpolation.js.map +1 -1
- package/build/dist/Utils/LegacySerializedArray.js +51 -0
- package/build/dist/Utils/LegacySerializedArray.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorDependencyRule.js +47 -0
- package/build/dist/Utils/Monitor/MonitorDependencyRule.js.map +1 -0
- package/build/dist/Utils/Telemetry/SavedViewFilters.js +52 -0
- package/build/dist/Utils/Telemetry/SavedViewFilters.js.map +1 -0
- package/jest.config.json +3 -0
- package/package.json +1 -1
- package/tsconfig.json +3 -1
|
@@ -65,6 +65,23 @@ export default class SendMessageToChannel extends ComponentCode {
|
|
|
65
65
|
);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/*
|
|
69
|
+
* Pin the target to Slack's own incoming-webhook endpoint. Without this the
|
|
70
|
+
* component POSTs from the API server to any URL a workflow author types -
|
|
71
|
+
* the SSRF reported as GHSA-v5xh-rw9h-77fv against the API components.
|
|
72
|
+
*/
|
|
73
|
+
if (
|
|
74
|
+
!SlackUtil.isValidSlackIncomingWebhookUrl(
|
|
75
|
+
args["webhook-url"]?.toString() as string,
|
|
76
|
+
)
|
|
77
|
+
) {
|
|
78
|
+
throw options.onError(
|
|
79
|
+
new BadDataException(
|
|
80
|
+
"Slack Webhook URL must start with https://hooks.slack.com/services/",
|
|
81
|
+
),
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
68
85
|
args["webhook-url"] = URL.fromString(
|
|
69
86
|
args["webhook-url"]?.toString() as string,
|
|
70
87
|
);
|
|
@@ -148,7 +148,7 @@ If the project has connected code repositories you can read their source, which
|
|
|
148
148
|
|
|
149
149
|
## Changing the code
|
|
150
150
|
|
|
151
|
-
You can propose code changes. open_code_pull_request is the right tool almost always: it opens a
|
|
151
|
+
You can propose code changes. open_code_pull_request is the right tool almost always: it opens a pull request off the default branch, ready for review, for a human to review and merge. commit_code_to_branch is only for when the user names an existing branch to commit onto.
|
|
152
152
|
|
|
153
153
|
- ALWAYS read_code_file the exact file first. \`content\` replaces the file's ENTIRE contents, so writing from memory or from a guess destroys code you never read. If you have not read it in this conversation, read it now.
|
|
154
154
|
- Never write to the default branch. The tools refuse it, and so should you — if the user asks you to commit straight to main/master, explain that changes go through a reviewable pull request.
|
|
@@ -13,6 +13,88 @@ import path from "path";
|
|
|
13
13
|
// Max characters a single tool result may feed back into the model.
|
|
14
14
|
export const MAX_TOOL_OUTPUT_CHARS: number = 20_000;
|
|
15
15
|
|
|
16
|
+
/*
|
|
17
|
+
* Max characters a single write_file may put on disk. A model that loops on
|
|
18
|
+
* a generation bug can otherwise fill the Runner's disk from inside a tool
|
|
19
|
+
* call, taking down every other capability on the host — and no legitimate
|
|
20
|
+
* source file a fix needs to write is anywhere near this size.
|
|
21
|
+
*/
|
|
22
|
+
export const MAX_WRITE_FILE_CHARS: number = 2_000_000;
|
|
23
|
+
|
|
24
|
+
/*
|
|
25
|
+
* Git subcommands the code agent may not run.
|
|
26
|
+
*
|
|
27
|
+
* The pipeline owns the repository's git state: it cuts the branch, decides
|
|
28
|
+
* what to stage, writes the commit and pushes. It also computes "what did
|
|
29
|
+
* the agent change" from the working tree. A model that helpfully commits
|
|
30
|
+
* its own work, resets the tree, switches branches or pushes therefore does
|
|
31
|
+
* not just duplicate the pipeline — it destroys the pipeline's ability to
|
|
32
|
+
* see the change at all (a committed tree is a clean tree, so the run
|
|
33
|
+
* reports "no changes" and the fix is silently discarded), or it puts a
|
|
34
|
+
* branch on the customer's remote that no pull request points at.
|
|
35
|
+
*
|
|
36
|
+
* The system prompt already asks the model not to. This is the enforcement,
|
|
37
|
+
* because an instruction is not a control.
|
|
38
|
+
*
|
|
39
|
+
* Honest about what this is: a guard against a well-meaning model taking an
|
|
40
|
+
* obvious wrong turn, NOT a sandbox. Shell is too expressive to filter
|
|
41
|
+
* adversarially — the real containment boundary is that the workspace is
|
|
42
|
+
* ephemeral, the credential is never in it, and nothing merges without a
|
|
43
|
+
* human. Read-only git (log, diff, status, show, grep, blame) stays
|
|
44
|
+
* available because the agent genuinely needs it.
|
|
45
|
+
*/
|
|
46
|
+
const REFUSED_GIT_SUBCOMMANDS: Set<string> = new Set<string>([
|
|
47
|
+
"push",
|
|
48
|
+
"commit",
|
|
49
|
+
"reset",
|
|
50
|
+
"checkout",
|
|
51
|
+
"switch",
|
|
52
|
+
"restore",
|
|
53
|
+
"stash",
|
|
54
|
+
"clean",
|
|
55
|
+
"rebase",
|
|
56
|
+
"merge",
|
|
57
|
+
"cherry-pick",
|
|
58
|
+
"revert",
|
|
59
|
+
"am",
|
|
60
|
+
"apply",
|
|
61
|
+
"filter-branch",
|
|
62
|
+
"update-ref",
|
|
63
|
+
"remote",
|
|
64
|
+
"config",
|
|
65
|
+
"credential",
|
|
66
|
+
"gc",
|
|
67
|
+
"prune",
|
|
68
|
+
]);
|
|
69
|
+
|
|
70
|
+
/*
|
|
71
|
+
* Shell operators that start a new command. Splitting on these is what lets
|
|
72
|
+
* the guard see the `git push` in `npm test && git push`.
|
|
73
|
+
*/
|
|
74
|
+
const COMMAND_SEPARATORS: RegExp = /(?:&&|\|\||[;\n|&()`]|\$\()/;
|
|
75
|
+
|
|
76
|
+
// A leading `VAR=value` assignment, which belongs to the command not to argv.
|
|
77
|
+
const LEADING_ENV_ASSIGNMENT: RegExp = /^[A-Za-z_][A-Za-z0-9_]*=/;
|
|
78
|
+
|
|
79
|
+
/*
|
|
80
|
+
* Options that take a separate value argument, so the subcommand is the
|
|
81
|
+
* token after next rather than the next token (`git -C sub push`).
|
|
82
|
+
*/
|
|
83
|
+
const GIT_OPTIONS_WITH_VALUE: Set<string> = new Set<string>([
|
|
84
|
+
"-C",
|
|
85
|
+
"-c",
|
|
86
|
+
"--git-dir",
|
|
87
|
+
"--work-tree",
|
|
88
|
+
"--namespace",
|
|
89
|
+
"--exec-path",
|
|
90
|
+
]);
|
|
91
|
+
|
|
92
|
+
export interface CommandGuardDecision {
|
|
93
|
+
allowed: boolean;
|
|
94
|
+
// Set when not allowed — the message handed back to the model.
|
|
95
|
+
reason: string | null;
|
|
96
|
+
}
|
|
97
|
+
|
|
16
98
|
export default class CodeAgentWorkspaceGuard {
|
|
17
99
|
/*
|
|
18
100
|
* Resolve a model-supplied path against the workspace root, refusing any
|
|
@@ -54,6 +136,95 @@ export default class CodeAgentWorkspaceGuard {
|
|
|
54
136
|
return relative === "" ? "." : relative;
|
|
55
137
|
}
|
|
56
138
|
|
|
139
|
+
/*
|
|
140
|
+
* Decide whether the agent may run a shell command.
|
|
141
|
+
*
|
|
142
|
+
* Only repository-state-mutating git is refused; everything else is
|
|
143
|
+
* allowed, because building and testing is the whole point of the tool.
|
|
144
|
+
* The refusal text names the reason so the model corrects course instead
|
|
145
|
+
* of retrying the same command.
|
|
146
|
+
*/
|
|
147
|
+
public static evaluateCommand(command: string): CommandGuardDecision {
|
|
148
|
+
for (const segment of command.split(COMMAND_SEPARATORS)) {
|
|
149
|
+
const subcommand: string | null = this.gitSubcommandOf(segment);
|
|
150
|
+
|
|
151
|
+
if (subcommand && REFUSED_GIT_SUBCOMMANDS.has(subcommand)) {
|
|
152
|
+
return {
|
|
153
|
+
allowed: false,
|
|
154
|
+
reason:
|
|
155
|
+
`Refused: \`git ${subcommand}\` is not available to you. The surrounding ` +
|
|
156
|
+
`pipeline owns this repository's git state — it created the branch, and it ` +
|
|
157
|
+
`stages, commits and pushes your changes once you are done. Running git ` +
|
|
158
|
+
`yourself would hide your work from it. Edit files with write_file and ` +
|
|
159
|
+
`leave git alone; read-only git (status, diff, log, show, grep) is allowed.`,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return { allowed: true, reason: null };
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/*
|
|
168
|
+
* The git subcommand a single shell segment invokes, or null when the
|
|
169
|
+
* segment does not invoke git. Skips leading environment assignments
|
|
170
|
+
* (`GIT_DIR=x git ...`) and git's own global options, including the ones
|
|
171
|
+
* that consume a following value.
|
|
172
|
+
*/
|
|
173
|
+
private static gitSubcommandOf(segment: string): string | null {
|
|
174
|
+
const tokens: Array<string> = segment
|
|
175
|
+
.trim()
|
|
176
|
+
.split(/\s+/)
|
|
177
|
+
.filter((token: string) => {
|
|
178
|
+
return token.length > 0;
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
let index: number = 0;
|
|
182
|
+
|
|
183
|
+
// Leading VAR=value assignments belong to the command, not to argv.
|
|
184
|
+
while (
|
|
185
|
+
index < tokens.length &&
|
|
186
|
+
LEADING_ENV_ASSIGNMENT.test(tokens[index] as string)
|
|
187
|
+
) {
|
|
188
|
+
index++;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const executable: string | undefined = tokens[index];
|
|
192
|
+
|
|
193
|
+
if (!executable) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Match `git`, `/usr/bin/git`, and `"git"` alike.
|
|
198
|
+
const executableName: string = executable
|
|
199
|
+
.replace(/^["']|["']$/g, "")
|
|
200
|
+
.split("/")
|
|
201
|
+
.pop() as string;
|
|
202
|
+
|
|
203
|
+
if (executableName !== "git") {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
index++;
|
|
208
|
+
|
|
209
|
+
while (index < tokens.length) {
|
|
210
|
+
const token: string = tokens[index] as string;
|
|
211
|
+
|
|
212
|
+
if (!token.startsWith("-")) {
|
|
213
|
+
return token.toLowerCase();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// `--git-dir=x` carries its value; `--git-dir x` consumes the next token.
|
|
217
|
+
if (GIT_OPTIONS_WITH_VALUE.has(token)) {
|
|
218
|
+
index += 2;
|
|
219
|
+
continue;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
index++;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
|
|
57
228
|
/*
|
|
58
229
|
* Truncate a tool output to the model-context cap, appending an explicit
|
|
59
230
|
* marker so the model knows the output is partial rather than complete.
|
|
@@ -39,9 +39,9 @@ import CaptureSpan from "../../Telemetry/CaptureSpan";
|
|
|
39
39
|
* same FixFromIncident task with no human click. Confidence alone is not
|
|
40
40
|
* sufficient: operational and other non-code causes do not open PRs. Like its
|
|
41
41
|
* InstrumentationTaskTrigger sibling it runs only after the Recommended
|
|
42
|
-
* decision and snapshot are durable, and it never throws. The PR
|
|
43
|
-
*
|
|
44
|
-
* PR creation to PR review, never past it.
|
|
42
|
+
* decision and snapshot are durable, and it never throws. The PR opens ready
|
|
43
|
+
* for review and is always human-reviewed — the opt-in moves the human gate
|
|
44
|
+
* from PR creation to PR review, never past it.
|
|
45
45
|
*/
|
|
46
46
|
|
|
47
47
|
export interface AutoFixTaskGateInput {
|
|
@@ -21,8 +21,9 @@ import CaptureSpan from "../../../Telemetry/CaptureSpan";
|
|
|
21
21
|
* Project.enableAi master switch AND on Project.enableInsightFixTasks
|
|
22
22
|
* (default FALSE): insights whose evidence points at code (new/spiking
|
|
23
23
|
* exceptions with a resolvable repository, latency regressions with
|
|
24
|
-
* span-tree findings) queue a CodeFix AIRun that opens a
|
|
25
|
-
*
|
|
24
|
+
* span-tree findings) queue a CodeFix AIRun that opens a pull request,
|
|
25
|
+
* ready for review. The decision is readiness/evidence-based, never
|
|
26
|
+
* LLM-decided.
|
|
26
27
|
*
|
|
27
28
|
* Everything downstream reuses the existing budgeted creation paths, so
|
|
28
29
|
* every guardrail comes free: the daily fix-run budget (G11, pre-checked
|
|
@@ -11,7 +11,7 @@ import CaptureSpan from "../../Telemetry/CaptureSpan";
|
|
|
11
11
|
/*
|
|
12
12
|
* AI SRE — the service-scoped instrumentation-improvement triggers:
|
|
13
13
|
* ImproveLogging and ImproveTracing. One click on a service's Logs or
|
|
14
|
-
* Traces page opens a
|
|
14
|
+
* Traces page opens a PR that improves that service's logging or
|
|
15
15
|
* tracing hygiene — parameterized log messages, correct severities, spans
|
|
16
16
|
* on uninstrumented paths, proper exception recording — WITHOUT changing
|
|
17
17
|
* behavior.
|
|
@@ -327,7 +327,7 @@ export const CommitCodeToBranchTool: ObservabilityTool = {
|
|
|
327
327
|
export const OpenCodePullRequestTool: ObservabilityTool = {
|
|
328
328
|
name: "open_code_pull_request",
|
|
329
329
|
description:
|
|
330
|
-
"Propose a code change: creates a new branch off the default branch, commits the changes, and opens a
|
|
330
|
+
"Propose a code change: creates a new branch off the default branch, commits the changes, and opens a pull request, ready for review, for a human to review and merge. This is the safe, preferred way to change code from chat — it never writes to the default branch and never merges. Read each file with read_code_file first: content replaces the whole file.",
|
|
331
331
|
isMutation: true,
|
|
332
332
|
inputSchema: {
|
|
333
333
|
type: "object",
|
|
@@ -358,7 +358,7 @@ export const OpenCodePullRequestTool: ObservabilityTool = {
|
|
|
358
358
|
return resolveUpdatePermissions();
|
|
359
359
|
},
|
|
360
360
|
buildActionTitle: (args: JSONObject): string => {
|
|
361
|
-
return `Open
|
|
361
|
+
return `Open pull request: ${ToolArgs.getString(args, "title") || "Untitled"}`;
|
|
362
362
|
},
|
|
363
363
|
execute: async (
|
|
364
364
|
args: JSONObject,
|
|
@@ -454,7 +454,7 @@ export const OpenCodePullRequestTool: ObservabilityTool = {
|
|
|
454
454
|
headBranchName: headBranchName,
|
|
455
455
|
title: title,
|
|
456
456
|
body: `${description}\n\n---\n_Proposed by OneUptime AI from a chat conversation. Review carefully before merging: this change was written by an agent that reads production telemetry._`,
|
|
457
|
-
isDraft:
|
|
457
|
+
isDraft: false,
|
|
458
458
|
});
|
|
459
459
|
|
|
460
460
|
/*
|
|
@@ -502,14 +502,14 @@ export const OpenCodePullRequestTool: ObservabilityTool = {
|
|
|
502
502
|
|
|
503
503
|
return {
|
|
504
504
|
dataForLlm: [
|
|
505
|
-
`Opened
|
|
505
|
+
`Opened pull request #${pullRequest.pullRequestNumber} on ${organizationName}/${repositoryName}, ready for review.`,
|
|
506
506
|
`url: ${pullRequestUrl}`,
|
|
507
507
|
`branch: ${headBranchName} → ${baseBranchName}`,
|
|
508
508
|
`files:\n${describeChanges(changes)}`,
|
|
509
|
-
`It is
|
|
509
|
+
`It is NOT merged. Give the user the link and say it needs their review.`,
|
|
510
510
|
].join("\n"),
|
|
511
511
|
rowCount: changes.length,
|
|
512
|
-
citationLabel: `
|
|
512
|
+
citationLabel: `PR #${pullRequest.pullRequestNumber}: ${title}`,
|
|
513
513
|
redactionCount: 0,
|
|
514
514
|
isTruncated: false,
|
|
515
515
|
};
|
|
@@ -1426,8 +1426,14 @@ export default class GitHubUtil extends HostedCodeRepository {
|
|
|
1426
1426
|
* sibling of the instance-method createPullRequest, which authenticates from
|
|
1427
1427
|
* a clone's own token.
|
|
1428
1428
|
*
|
|
1429
|
-
* Opened
|
|
1430
|
-
*
|
|
1429
|
+
* Opened READY FOR REVIEW by default: a draft never reaches reviewers,
|
|
1430
|
+
* CODEOWNERS or review automation, which buried the work instead of
|
|
1431
|
+
* surfacing it. Human review is still mandatory — the safety boundary is
|
|
1432
|
+
* that we only ever write to a fresh branch and never merge anything.
|
|
1433
|
+
*
|
|
1434
|
+
* Pass isDraft: true to open a draft instead; GitHub answers 422 for
|
|
1435
|
+
* repositories whose plan lacks drafts, and we then retry ready-for-review
|
|
1436
|
+
* rather than losing the work.
|
|
1431
1437
|
*/
|
|
1432
1438
|
@CaptureSpan()
|
|
1433
1439
|
public static async createPullRequestWithToken(data: {
|
|
@@ -1450,7 +1456,7 @@ export default class GitHubUtil extends HostedCodeRepository {
|
|
|
1450
1456
|
`https://api.github.com/repos/${data.organizationName}/${data.repositoryName}/pulls`,
|
|
1451
1457
|
);
|
|
1452
1458
|
|
|
1453
|
-
const wantsDraft: boolean = data.isDraft
|
|
1459
|
+
const wantsDraft: boolean = data.isDraft === true;
|
|
1454
1460
|
|
|
1455
1461
|
let result: HTTPErrorResponse | HTTPResponse<JSONObject> = await API.post({
|
|
1456
1462
|
url: url,
|
|
@@ -1464,13 +1470,19 @@ export default class GitHubUtil extends HostedCodeRepository {
|
|
|
1464
1470
|
headers: headers,
|
|
1465
1471
|
});
|
|
1466
1472
|
|
|
1473
|
+
/*
|
|
1474
|
+
* Only retry when GitHub refused the DRAFT state specifically. A 422 is
|
|
1475
|
+
* also how it reports "a pull request already exists for this branch" and
|
|
1476
|
+
* an invalid head — retrying those just fails a second time and hides the
|
|
1477
|
+
* real message behind a misleading one.
|
|
1478
|
+
*/
|
|
1467
1479
|
if (
|
|
1468
1480
|
result instanceof HTTPErrorResponse &&
|
|
1469
1481
|
wantsDraft &&
|
|
1470
|
-
result
|
|
1482
|
+
GitHubUtil.isDraftNotSupportedError(result)
|
|
1471
1483
|
) {
|
|
1472
1484
|
logger.debug(
|
|
1473
|
-
`GitHub rejected the draft pull request for ${data.organizationName}/${data.repositoryName}; retrying as
|
|
1485
|
+
`GitHub rejected the draft pull request for ${data.organizationName}/${data.repositoryName}; retrying as ready-for-review.`,
|
|
1474
1486
|
);
|
|
1475
1487
|
|
|
1476
1488
|
result = await API.post({
|
|
@@ -1480,6 +1492,7 @@ export default class GitHubUtil extends HostedCodeRepository {
|
|
|
1480
1492
|
head: data.headBranchName,
|
|
1481
1493
|
title: data.title,
|
|
1482
1494
|
body: data.body,
|
|
1495
|
+
draft: false,
|
|
1483
1496
|
},
|
|
1484
1497
|
headers: headers,
|
|
1485
1498
|
});
|
|
@@ -1499,6 +1512,31 @@ export default class GitHubUtil extends HostedCodeRepository {
|
|
|
1499
1512
|
});
|
|
1500
1513
|
}
|
|
1501
1514
|
|
|
1515
|
+
/*
|
|
1516
|
+
* True when a failed create-PR response is GitHub refusing the DRAFT state
|
|
1517
|
+
* specifically — an HTTP 422 whose message or errors name drafts, e.g.
|
|
1518
|
+
* "Draft pull requests are not supported in this repository."
|
|
1519
|
+
*
|
|
1520
|
+
* Every other 422 (a pull request already exists for this branch, an
|
|
1521
|
+
* invalid head, a validation failure) must NOT trigger the ready-for-review
|
|
1522
|
+
* retry: the retry would fail identically and the caller would be handed the
|
|
1523
|
+
* second error, which no longer describes the real problem.
|
|
1524
|
+
*/
|
|
1525
|
+
public static isDraftNotSupportedError(response: HTTPErrorResponse): boolean {
|
|
1526
|
+
if (response.statusCode !== 422) {
|
|
1527
|
+
return false;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
const errorData: JSONObject = (response.data as JSONObject) || {};
|
|
1531
|
+
|
|
1532
|
+
const textParts: Array<string> = [
|
|
1533
|
+
(errorData["message"] as string) || "",
|
|
1534
|
+
JSON.stringify(errorData["errors"] || ""),
|
|
1535
|
+
];
|
|
1536
|
+
|
|
1537
|
+
return textParts.join(" ").toLowerCase().includes("draft");
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1502
1540
|
/*
|
|
1503
1541
|
* Every blob path in a tree mapped to its git file mode, so a rewrite can
|
|
1504
1542
|
* preserve the mode instead of flattening everything to 100644. Recursive
|
|
@@ -1,16 +1,26 @@
|
|
|
1
1
|
import dns from "dns";
|
|
2
|
+
import http from "http";
|
|
3
|
+
import https from "https";
|
|
2
4
|
import net from "net";
|
|
3
5
|
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
4
|
-
import { IsBillingEnabled } from "../../EnvironmentConfig";
|
|
5
6
|
|
|
6
7
|
/*
|
|
7
|
-
* SSRF egress guard for
|
|
8
|
+
* SSRF egress guard for outbound connections whose target is chosen by a
|
|
9
|
+
* tenant.
|
|
8
10
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* internal
|
|
13
|
-
*
|
|
11
|
+
* It started life guarding external Data Source connections — hence the
|
|
12
|
+
* file's home — but the same policy now covers every sink where a project
|
|
13
|
+
* member picks the host and a self-hosted install may legitimately point at
|
|
14
|
+
* something internal: LLM providers (self-hosted Ollama/vLLM), SMTP OAuth
|
|
15
|
+
* token endpoints, status page / dashboard domain verification, OIDC
|
|
16
|
+
* discovery and Runbook HTTP steps. Sinks that can only ever be third-party
|
|
17
|
+
* SaaS (Slack, Teams, subscriber webhooks) use SSRFProtection instead, which
|
|
18
|
+
* blocks private ranges unconditionally.
|
|
19
|
+
*
|
|
20
|
+
* Without a guard these turn the API server into an authenticated request
|
|
21
|
+
* proxy into whatever network it runs in (cloud metadata endpoints, internal
|
|
22
|
+
* services, sibling tenants' infrastructure). Every caller must validate its
|
|
23
|
+
* target through this guard before opening a socket.
|
|
14
24
|
*
|
|
15
25
|
* Policy:
|
|
16
26
|
* - ALWAYS blocked, in every deployment: loopback, link-local (cloud
|
|
@@ -51,8 +61,38 @@ export interface EgressGuardOptions {
|
|
|
51
61
|
blockPrivateAddresses?: boolean | undefined;
|
|
52
62
|
// Test seam for DNS. Undefined ⇒ dns.promises.lookup with a timeout.
|
|
53
63
|
resolveFunction?: EgressResolveFunction | undefined;
|
|
64
|
+
/*
|
|
65
|
+
* Noun used in error messages so a rejection names the thing the user was
|
|
66
|
+
* actually configuring ("LLM provider host ... is not allowed"). Defaults
|
|
67
|
+
* to "Data source".
|
|
68
|
+
*/
|
|
69
|
+
targetLabel?: string | undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export interface PinnedAgents {
|
|
73
|
+
httpAgent: http.Agent;
|
|
74
|
+
httpsAgent: https.Agent;
|
|
54
75
|
}
|
|
55
76
|
|
|
77
|
+
/*
|
|
78
|
+
* dns.lookup's shape, as http.Agent / net.Socket call it. Declared locally
|
|
79
|
+
* rather than pulled from @types/node because the real declaration is a heavy
|
|
80
|
+
* overload set and every consumer here uses exactly this one shape.
|
|
81
|
+
*/
|
|
82
|
+
export type EgressLookupCallback = (
|
|
83
|
+
error: NodeJS.ErrnoException | null,
|
|
84
|
+
address: string | Array<{ address: string; family: number }>,
|
|
85
|
+
family?: number,
|
|
86
|
+
) => void;
|
|
87
|
+
|
|
88
|
+
export type EgressLookupFunction = (
|
|
89
|
+
hostname: string,
|
|
90
|
+
options: { all?: boolean | undefined; family?: number | undefined },
|
|
91
|
+
callback: EgressLookupCallback,
|
|
92
|
+
) => void;
|
|
93
|
+
|
|
94
|
+
const DEFAULT_TARGET_LABEL: string = "Data source";
|
|
95
|
+
|
|
56
96
|
export interface AddressVerdict {
|
|
57
97
|
blocked: boolean;
|
|
58
98
|
reason?: string | undefined;
|
|
@@ -93,7 +133,15 @@ export default class DataSourceEgressGuard {
|
|
|
93
133
|
if (process.env["DATA_SOURCE_BLOCK_PRIVATE_ADDRESSES"] === "true") {
|
|
94
134
|
return true;
|
|
95
135
|
}
|
|
96
|
-
|
|
136
|
+
/*
|
|
137
|
+
* Read BILLING_ENABLED at call time rather than the boot-time
|
|
138
|
+
* IsBillingEnabled const, so this policy is consistent with the env
|
|
139
|
+
* override checked above and can be exercised deterministically in tests
|
|
140
|
+
* (a self-hosted install with billing off must still be able to reach its
|
|
141
|
+
* own private ranges). In a running deployment the env is fixed at boot,
|
|
142
|
+
* so this is behaviourally identical to the const.
|
|
143
|
+
*/
|
|
144
|
+
return process.env["BILLING_ENABLED"] === "true";
|
|
97
145
|
}
|
|
98
146
|
|
|
99
147
|
private static ipv4ToInt(ip: string): number {
|
|
@@ -352,8 +400,10 @@ export default class DataSourceEgressGuard {
|
|
|
352
400
|
hostname: string,
|
|
353
401
|
options?: EgressGuardOptions,
|
|
354
402
|
): Promise<Array<ResolvedAddress>> {
|
|
403
|
+
const label: string = options?.targetLabel || DEFAULT_TARGET_LABEL;
|
|
404
|
+
|
|
355
405
|
if (!hostname) {
|
|
356
|
-
throw new BadDataException(
|
|
406
|
+
throw new BadDataException(`${label} host is required.`);
|
|
357
407
|
}
|
|
358
408
|
|
|
359
409
|
// Literal [::1] style hosts arrive with brackets from URL parsing.
|
|
@@ -363,7 +413,7 @@ export default class DataSourceEgressGuard {
|
|
|
363
413
|
const verdict: AddressVerdict = this.checkAddress(bareHostname, options);
|
|
364
414
|
if (verdict.blocked) {
|
|
365
415
|
throw new BadDataException(
|
|
366
|
-
|
|
416
|
+
`${label} host ${bareHostname} is not allowed: ${verdict.reason}.`,
|
|
367
417
|
);
|
|
368
418
|
}
|
|
369
419
|
return [{ address: bareHostname, family: net.isIP(bareHostname) }];
|
|
@@ -380,7 +430,7 @@ export default class DataSourceEgressGuard {
|
|
|
380
430
|
addresses = await resolveFunction(bareHostname);
|
|
381
431
|
} catch (error) {
|
|
382
432
|
throw new BadDataException(
|
|
383
|
-
`Could not resolve
|
|
433
|
+
`Could not resolve ${label.toLowerCase()} host ${bareHostname}: ${
|
|
384
434
|
error instanceof Error ? error.message : String(error)
|
|
385
435
|
}`,
|
|
386
436
|
);
|
|
@@ -388,7 +438,7 @@ export default class DataSourceEgressGuard {
|
|
|
388
438
|
|
|
389
439
|
if (addresses.length === 0) {
|
|
390
440
|
throw new BadDataException(
|
|
391
|
-
`Could not resolve
|
|
441
|
+
`Could not resolve ${label.toLowerCase()} host ${bareHostname}.`,
|
|
392
442
|
);
|
|
393
443
|
}
|
|
394
444
|
|
|
@@ -399,7 +449,7 @@ export default class DataSourceEgressGuard {
|
|
|
399
449
|
);
|
|
400
450
|
if (verdict.blocked) {
|
|
401
451
|
throw new BadDataException(
|
|
402
|
-
|
|
452
|
+
`${label} host ${bareHostname} resolves to ${resolved.address}, which is not allowed: ${verdict.reason}.`,
|
|
403
453
|
);
|
|
404
454
|
}
|
|
405
455
|
}
|
|
@@ -416,20 +466,24 @@ export default class DataSourceEgressGuard {
|
|
|
416
466
|
urlString: string,
|
|
417
467
|
options?: EgressGuardOptions,
|
|
418
468
|
): Promise<{ url: URL; addresses: Array<ResolvedAddress> }> {
|
|
469
|
+
const label: string = options?.targetLabel || DEFAULT_TARGET_LABEL;
|
|
470
|
+
|
|
419
471
|
if (!urlString) {
|
|
420
|
-
throw new BadDataException(
|
|
472
|
+
throw new BadDataException(`${label} URL is required.`);
|
|
421
473
|
}
|
|
422
474
|
|
|
423
475
|
let url: URL;
|
|
424
476
|
try {
|
|
425
477
|
url = new URL(urlString);
|
|
426
478
|
} catch {
|
|
427
|
-
throw new BadDataException(
|
|
479
|
+
throw new BadDataException(
|
|
480
|
+
`Invalid ${label.toLowerCase()} URL: ${urlString}`,
|
|
481
|
+
);
|
|
428
482
|
}
|
|
429
483
|
|
|
430
484
|
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
431
485
|
throw new BadDataException(
|
|
432
|
-
|
|
486
|
+
`${label} URL must use http or https (got ${url.protocol.replace(
|
|
433
487
|
":",
|
|
434
488
|
"",
|
|
435
489
|
)}).`,
|
|
@@ -443,4 +497,110 @@ export default class DataSourceEgressGuard {
|
|
|
443
497
|
|
|
444
498
|
return { url, addresses };
|
|
445
499
|
}
|
|
500
|
+
|
|
501
|
+
/*
|
|
502
|
+
* A dns.lookup-shaped function that always answers with the already
|
|
503
|
+
* validated addresses. Handing this to an http(s).Agent makes the address
|
|
504
|
+
* that was checked the address that gets dialed, closing the DNS-rebind
|
|
505
|
+
* window between validation and connect. TLS still verifies against the
|
|
506
|
+
* original hostname because SNI is taken from the URL, not from here.
|
|
507
|
+
*/
|
|
508
|
+
public static createPinnedLookup(
|
|
509
|
+
addresses: Array<ResolvedAddress>,
|
|
510
|
+
): EgressLookupFunction {
|
|
511
|
+
return (
|
|
512
|
+
_hostname: string,
|
|
513
|
+
lookupOptions: { all?: boolean | undefined },
|
|
514
|
+
callback: EgressLookupCallback,
|
|
515
|
+
): void => {
|
|
516
|
+
if (lookupOptions && lookupOptions.all) {
|
|
517
|
+
callback(
|
|
518
|
+
null,
|
|
519
|
+
addresses.map((resolved: ResolvedAddress) => {
|
|
520
|
+
return { address: resolved.address, family: resolved.family };
|
|
521
|
+
}),
|
|
522
|
+
);
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const first: ResolvedAddress = addresses[0]!;
|
|
527
|
+
callback(null, first.address, first.family);
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
// http/https agent pair that dials only the given validated addresses.
|
|
532
|
+
public static createPinnedAgents(
|
|
533
|
+
addresses: Array<ResolvedAddress>,
|
|
534
|
+
): PinnedAgents {
|
|
535
|
+
const lookup: EgressLookupFunction = this.createPinnedLookup(addresses);
|
|
536
|
+
|
|
537
|
+
return {
|
|
538
|
+
httpAgent: new http.Agent({ lookup: lookup as never }),
|
|
539
|
+
httpsAgent: new https.Agent({ lookup: lookup as never }),
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/*
|
|
544
|
+
* Validate a URL and return agents pinned to what it resolved to — the
|
|
545
|
+
* one-call form for HTTP callers. Pair with maxRedirects 0 /
|
|
546
|
+
* doNotFollowRedirects: pinning only covers the host that was validated, so
|
|
547
|
+
* a 3xx to an unvalidated host would otherwise walk straight around it.
|
|
548
|
+
*/
|
|
549
|
+
public static async assertUrlAllowedAndPin(
|
|
550
|
+
urlString: string,
|
|
551
|
+
options?: EgressGuardOptions,
|
|
552
|
+
): Promise<{ url: URL; addresses: Array<ResolvedAddress> } & PinnedAgents> {
|
|
553
|
+
const { url, addresses } = await this.assertUrlAllowed(urlString, options);
|
|
554
|
+
|
|
555
|
+
return { url, addresses, ...this.createPinnedAgents(addresses) };
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/*
|
|
559
|
+
* A dns.lookup-shaped function that validates every hostname it is asked
|
|
560
|
+
* about and then answers with the addresses it just checked.
|
|
561
|
+
*
|
|
562
|
+
* For libraries that build their own request URLs from documents they
|
|
563
|
+
* fetched (openid-client adopts token_endpoint/userinfo_endpoint/jwks_uri
|
|
564
|
+
* from the discovery document), pre-validating the one URL we know about
|
|
565
|
+
* fixes nothing. Installing this as the library's lookup puts the guard on
|
|
566
|
+
* every socket the library opens, whichever URL it decided to call.
|
|
567
|
+
*/
|
|
568
|
+
public static createGuardedLookup(
|
|
569
|
+
options?: EgressGuardOptions,
|
|
570
|
+
): EgressLookupFunction {
|
|
571
|
+
return (
|
|
572
|
+
hostname: string,
|
|
573
|
+
lookupOptions: { all?: boolean | undefined; family?: number | undefined },
|
|
574
|
+
callback: EgressLookupCallback,
|
|
575
|
+
): void => {
|
|
576
|
+
this.assertHostnameAllowed(hostname, options)
|
|
577
|
+
.then((addresses: Array<ResolvedAddress>) => {
|
|
578
|
+
const wantedFamily: number | undefined =
|
|
579
|
+
lookupOptions && lookupOptions.family
|
|
580
|
+
? lookupOptions.family
|
|
581
|
+
: undefined;
|
|
582
|
+
|
|
583
|
+
const usable: Array<ResolvedAddress> =
|
|
584
|
+
wantedFamily === 4 || wantedFamily === 6
|
|
585
|
+
? addresses.filter((resolved: ResolvedAddress) => {
|
|
586
|
+
return resolved.family === wantedFamily;
|
|
587
|
+
})
|
|
588
|
+
: addresses;
|
|
589
|
+
|
|
590
|
+
if (usable.length === 0) {
|
|
591
|
+
const error: NodeJS.ErrnoException = new Error(
|
|
592
|
+
`No IPv${wantedFamily} address for ${hostname}`,
|
|
593
|
+
);
|
|
594
|
+
error.code = "ENOTFOUND";
|
|
595
|
+
callback(error, "");
|
|
596
|
+
return;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
this.createPinnedLookup(usable)(hostname, lookupOptions, callback);
|
|
600
|
+
})
|
|
601
|
+
.catch((error: Error) => {
|
|
602
|
+
callback(error as NodeJS.ErrnoException, "");
|
|
603
|
+
});
|
|
604
|
+
};
|
|
605
|
+
}
|
|
446
606
|
}
|