@meyicloud/meyi-insight-server 1.0.0
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/dist/constants/incidentCategories.d.ts +18 -0
- package/dist/constants/incidentCategories.d.ts.map +1 -0
- package/dist/constants/incidentCategories.js +36 -0
- package/dist/constants/incidentCategories.js.map +1 -0
- package/dist/controllers/alert.controller.d.ts +12 -0
- package/dist/controllers/alert.controller.d.ts.map +1 -0
- package/dist/controllers/alert.controller.js +89 -0
- package/dist/controllers/alert.controller.js.map +1 -0
- package/dist/controllers/incident.controller.d.ts +16 -0
- package/dist/controllers/incident.controller.d.ts.map +1 -0
- package/dist/controllers/incident.controller.js +215 -0
- package/dist/controllers/incident.controller.js.map +1 -0
- package/dist/controllers/notification-provider.controller.d.ts +10 -0
- package/dist/controllers/notification-provider.controller.d.ts.map +1 -0
- package/dist/controllers/notification-provider.controller.js +59 -0
- package/dist/controllers/notification-provider.controller.js.map +1 -0
- package/dist/controllers/settings.controller.d.ts +7 -0
- package/dist/controllers/settings.controller.d.ts.map +1 -0
- package/dist/controllers/settings.controller.js +27 -0
- package/dist/controllers/settings.controller.js.map +1 -0
- package/dist/controllers/sop.controller.d.ts +11 -0
- package/dist/controllers/sop.controller.d.ts.map +1 -0
- package/dist/controllers/sop.controller.js +89 -0
- package/dist/controllers/sop.controller.js.map +1 -0
- package/dist/controllers/source.controller.d.ts +26 -0
- package/dist/controllers/source.controller.d.ts.map +1 -0
- package/dist/controllers/source.controller.js +333 -0
- package/dist/controllers/source.controller.js.map +1 -0
- package/dist/controllers/sourceDatadog.controller.d.ts +17 -0
- package/dist/controllers/sourceDatadog.controller.d.ts.map +1 -0
- package/dist/controllers/sourceDatadog.controller.js +169 -0
- package/dist/controllers/sourceDatadog.controller.js.map +1 -0
- package/dist/controllers/tenant.controller.d.ts +7 -0
- package/dist/controllers/tenant.controller.d.ts.map +1 -0
- package/dist/controllers/tenant.controller.js +33 -0
- package/dist/controllers/tenant.controller.js.map +1 -0
- package/dist/controllers/webhook.controller.d.ts +6 -0
- package/dist/controllers/webhook.controller.d.ts.map +1 -0
- package/dist/controllers/webhook.controller.js +83 -0
- package/dist/controllers/webhook.controller.js.map +1 -0
- package/dist/controllers/workflow.controller.d.ts +18 -0
- package/dist/controllers/workflow.controller.d.ts.map +1 -0
- package/dist/controllers/workflow.controller.js +118 -0
- package/dist/controllers/workflow.controller.js.map +1 -0
- package/dist/database/index.d.ts +7 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +12 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/schema.d.ts +5358 -0
- package/dist/database/schema.d.ts.map +1 -0
- package/dist/database/schema.js +516 -0
- package/dist/database/schema.js.map +1 -0
- package/dist/features/sources/cloudtrail/controller.d.ts +38 -0
- package/dist/features/sources/cloudtrail/controller.d.ts.map +1 -0
- package/dist/features/sources/cloudtrail/controller.js +421 -0
- package/dist/features/sources/cloudtrail/controller.js.map +1 -0
- package/dist/features/sources/cloudtrail/routes.d.ts +6 -0
- package/dist/features/sources/cloudtrail/routes.d.ts.map +1 -0
- package/dist/features/sources/cloudtrail/routes.js +8 -0
- package/dist/features/sources/cloudtrail/routes.js.map +1 -0
- package/dist/features/sources/cloudtrail/schema.d.ts +2 -0
- package/dist/features/sources/cloudtrail/schema.d.ts.map +1 -0
- package/dist/features/sources/cloudtrail/schema.js +26 -0
- package/dist/features/sources/cloudtrail/schema.js.map +1 -0
- package/dist/features/sources/cloudtrail/stackTemplates.d.ts +3 -0
- package/dist/features/sources/cloudtrail/stackTemplates.d.ts.map +1 -0
- package/dist/features/sources/cloudtrail/stackTemplates.js +548 -0
- package/dist/features/sources/cloudtrail/stackTemplates.js.map +1 -0
- package/dist/features/sources/cloudtrail/template.d.ts +21 -0
- package/dist/features/sources/cloudtrail/template.d.ts.map +1 -0
- package/dist/features/sources/cloudtrail/template.js +1230 -0
- package/dist/features/sources/cloudtrail/template.js.map +1 -0
- package/dist/features/sources/cloudwatch/controller.d.ts +13 -0
- package/dist/features/sources/cloudwatch/controller.d.ts.map +1 -0
- package/dist/features/sources/cloudwatch/controller.js +514 -0
- package/dist/features/sources/cloudwatch/controller.js.map +1 -0
- package/dist/features/sources/cloudwatch/eventbridgeTemplate.d.ts +7 -0
- package/dist/features/sources/cloudwatch/eventbridgeTemplate.d.ts.map +1 -0
- package/dist/features/sources/cloudwatch/eventbridgeTemplate.js +230 -0
- package/dist/features/sources/cloudwatch/eventbridgeTemplate.js.map +1 -0
- package/dist/features/sources/cloudwatch/service.d.ts +50 -0
- package/dist/features/sources/cloudwatch/service.d.ts.map +1 -0
- package/dist/features/sources/cloudwatch/service.js +269 -0
- package/dist/features/sources/cloudwatch/service.js.map +1 -0
- package/dist/features/sources/cloudwatch/template.d.ts +26 -0
- package/dist/features/sources/cloudwatch/template.d.ts.map +1 -0
- package/dist/features/sources/cloudwatch/template.js +335 -0
- package/dist/features/sources/cloudwatch/template.js.map +1 -0
- package/dist/features/sources/cloudwatch/types.d.ts +26 -0
- package/dist/features/sources/cloudwatch/types.d.ts.map +1 -0
- package/dist/features/sources/cloudwatch/types.js +2 -0
- package/dist/features/sources/cloudwatch/types.js.map +1 -0
- package/dist/features/sources/grafana/controller.d.ts +18 -0
- package/dist/features/sources/grafana/controller.d.ts.map +1 -0
- package/dist/features/sources/grafana/controller.js +183 -0
- package/dist/features/sources/grafana/controller.js.map +1 -0
- package/dist/features/sources/grafana/routes.d.ts +6 -0
- package/dist/features/sources/grafana/routes.d.ts.map +1 -0
- package/dist/features/sources/grafana/routes.js +6 -0
- package/dist/features/sources/grafana/routes.js.map +1 -0
- package/dist/features/sources/grafana/schema.d.ts +2 -0
- package/dist/features/sources/grafana/schema.d.ts.map +1 -0
- package/dist/features/sources/grafana/schema.js +24 -0
- package/dist/features/sources/grafana/schema.js.map +1 -0
- package/dist/features/sources/grafana/service.d.ts +33 -0
- package/dist/features/sources/grafana/service.d.ts.map +1 -0
- package/dist/features/sources/grafana/service.js +215 -0
- package/dist/features/sources/grafana/service.js.map +1 -0
- package/dist/features/sources/index.d.ts +29 -0
- package/dist/features/sources/index.d.ts.map +1 -0
- package/dist/features/sources/index.js +47 -0
- package/dist/features/sources/index.js.map +1 -0
- package/dist/features/sources/observability/controller.d.ts +6 -0
- package/dist/features/sources/observability/controller.d.ts.map +1 -0
- package/dist/features/sources/observability/controller.js +16 -0
- package/dist/features/sources/observability/controller.js.map +1 -0
- package/dist/features/sources/observability/routes.d.ts +4 -0
- package/dist/features/sources/observability/routes.d.ts.map +1 -0
- package/dist/features/sources/observability/routes.js +8 -0
- package/dist/features/sources/observability/routes.js.map +1 -0
- package/dist/features/sources/observability/schema.d.ts +3 -0
- package/dist/features/sources/observability/schema.d.ts.map +1 -0
- package/dist/features/sources/observability/schema.js +44 -0
- package/dist/features/sources/observability/schema.js.map +1 -0
- package/dist/features/sources/observability/service.d.ts +36 -0
- package/dist/features/sources/observability/service.d.ts.map +1 -0
- package/dist/features/sources/observability/service.js +127 -0
- package/dist/features/sources/observability/service.js.map +1 -0
- package/dist/features/sources/prometheus/controller.d.ts +9 -0
- package/dist/features/sources/prometheus/controller.d.ts.map +1 -0
- package/dist/features/sources/prometheus/controller.js +359 -0
- package/dist/features/sources/prometheus/controller.js.map +1 -0
- package/dist/features/sources/prometheus/templates.d.ts +18 -0
- package/dist/features/sources/prometheus/templates.d.ts.map +1 -0
- package/dist/features/sources/prometheus/templates.js +244 -0
- package/dist/features/sources/prometheus/templates.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/migrations/0007_pipeline_yaml_definitions.d.ts +3 -0
- package/dist/migrations/0007_pipeline_yaml_definitions.d.ts.map +1 -0
- package/dist/migrations/0007_pipeline_yaml_definitions.js +19 -0
- package/dist/migrations/0007_pipeline_yaml_definitions.js.map +1 -0
- package/dist/migrations/0008_tenant_isolation.d.ts +3 -0
- package/dist/migrations/0008_tenant_isolation.d.ts.map +1 -0
- package/dist/migrations/0008_tenant_isolation.js +42 -0
- package/dist/migrations/0008_tenant_isolation.js.map +1 -0
- package/dist/migrations/run.d.ts +6 -0
- package/dist/migrations/run.d.ts.map +1 -0
- package/dist/migrations/run.js +1262 -0
- package/dist/migrations/run.js.map +1 -0
- package/dist/models/alarm-group.model.d.ts +42 -0
- package/dist/models/alarm-group.model.d.ts.map +1 -0
- package/dist/models/alarm-group.model.js +98 -0
- package/dist/models/alarm-group.model.js.map +1 -0
- package/dist/models/alert.model.d.ts +54 -0
- package/dist/models/alert.model.d.ts.map +1 -0
- package/dist/models/alert.model.js +119 -0
- package/dist/models/alert.model.js.map +1 -0
- package/dist/models/dedup-config.model.d.ts +53 -0
- package/dist/models/dedup-config.model.d.ts.map +1 -0
- package/dist/models/dedup-config.model.js +157 -0
- package/dist/models/dedup-config.model.js.map +1 -0
- package/dist/models/grouping-config.model.d.ts +70 -0
- package/dist/models/grouping-config.model.d.ts.map +1 -0
- package/dist/models/grouping-config.model.js +174 -0
- package/dist/models/grouping-config.model.js.map +1 -0
- package/dist/models/incident-comment.model.d.ts +14 -0
- package/dist/models/incident-comment.model.d.ts.map +1 -0
- package/dist/models/incident-comment.model.js +38 -0
- package/dist/models/incident-comment.model.js.map +1 -0
- package/dist/models/incident-event.model.d.ts +16 -0
- package/dist/models/incident-event.model.d.ts.map +1 -0
- package/dist/models/incident-event.model.js +31 -0
- package/dist/models/incident-event.model.js.map +1 -0
- package/dist/models/incident.model.d.ts +47 -0
- package/dist/models/incident.model.d.ts.map +1 -0
- package/dist/models/incident.model.js +201 -0
- package/dist/models/incident.model.js.map +1 -0
- package/dist/models/normalization-config.model.d.ts +44 -0
- package/dist/models/normalization-config.model.d.ts.map +1 -0
- package/dist/models/normalization-config.model.js +153 -0
- package/dist/models/normalization-config.model.js.map +1 -0
- package/dist/models/notification-provider.model.d.ts +12 -0
- package/dist/models/notification-provider.model.d.ts.map +1 -0
- package/dist/models/notification-provider.model.js +48 -0
- package/dist/models/notification-provider.model.js.map +1 -0
- package/dist/models/pipeline-event.model.d.ts +15 -0
- package/dist/models/pipeline-event.model.d.ts.map +1 -0
- package/dist/models/pipeline-event.model.js +32 -0
- package/dist/models/pipeline-event.model.js.map +1 -0
- package/dist/models/settings.model.d.ts +8 -0
- package/dist/models/settings.model.d.ts.map +1 -0
- package/dist/models/settings.model.js +30 -0
- package/dist/models/settings.model.js.map +1 -0
- package/dist/models/sop.model.d.ts +58 -0
- package/dist/models/sop.model.d.ts.map +1 -0
- package/dist/models/sop.model.js +138 -0
- package/dist/models/sop.model.js.map +1 -0
- package/dist/models/source.model.d.ts +177 -0
- package/dist/models/source.model.d.ts.map +1 -0
- package/dist/models/source.model.js +794 -0
- package/dist/models/source.model.js.map +1 -0
- package/dist/models/tenant.model.d.ts +13 -0
- package/dist/models/tenant.model.d.ts.map +1 -0
- package/dist/models/tenant.model.js +28 -0
- package/dist/models/tenant.model.js.map +1 -0
- package/dist/models/workflow.model.d.ts +36 -0
- package/dist/models/workflow.model.d.ts.map +1 -0
- package/dist/models/workflow.model.js +136 -0
- package/dist/models/workflow.model.js.map +1 -0
- package/dist/pipeline/AlarmPipelineWorker.d.ts +18 -0
- package/dist/pipeline/AlarmPipelineWorker.d.ts.map +1 -0
- package/dist/pipeline/AlarmPipelineWorker.js +342 -0
- package/dist/pipeline/AlarmPipelineWorker.js.map +1 -0
- package/dist/pipeline/CanonicalAlarm.d.ts +59 -0
- package/dist/pipeline/CanonicalAlarm.d.ts.map +1 -0
- package/dist/pipeline/CanonicalAlarm.js +81 -0
- package/dist/pipeline/CanonicalAlarm.js.map +1 -0
- package/dist/pipeline/DedupService.d.ts +29 -0
- package/dist/pipeline/DedupService.d.ts.map +1 -0
- package/dist/pipeline/DedupService.js +172 -0
- package/dist/pipeline/DedupService.js.map +1 -0
- package/dist/pipeline/GroupFlushWorker.d.ts +16 -0
- package/dist/pipeline/GroupFlushWorker.d.ts.map +1 -0
- package/dist/pipeline/GroupFlushWorker.js +196 -0
- package/dist/pipeline/GroupFlushWorker.js.map +1 -0
- package/dist/pipeline/GroupingService.d.ts +27 -0
- package/dist/pipeline/GroupingService.d.ts.map +1 -0
- package/dist/pipeline/GroupingService.js +338 -0
- package/dist/pipeline/GroupingService.js.map +1 -0
- package/dist/pipeline/NormalizationRuleEngine.d.ts +5 -0
- package/dist/pipeline/NormalizationRuleEngine.d.ts.map +1 -0
- package/dist/pipeline/NormalizationRuleEngine.js +86 -0
- package/dist/pipeline/NormalizationRuleEngine.js.map +1 -0
- package/dist/pipeline/NormalizationService.d.ts +29 -0
- package/dist/pipeline/NormalizationService.d.ts.map +1 -0
- package/dist/pipeline/NormalizationService.js +275 -0
- package/dist/pipeline/NormalizationService.js.map +1 -0
- package/dist/pipeline/alarmQueue.d.ts +66 -0
- package/dist/pipeline/alarmQueue.d.ts.map +1 -0
- package/dist/pipeline/alarmQueue.js +254 -0
- package/dist/pipeline/alarmQueue.js.map +1 -0
- package/dist/pipeline/defaults/ensureDefaults.d.ts +3 -0
- package/dist/pipeline/defaults/ensureDefaults.d.ts.map +1 -0
- package/dist/pipeline/defaults/ensureDefaults.js +124 -0
- package/dist/pipeline/defaults/ensureDefaults.js.map +1 -0
- package/dist/pipeline/defaults/pipelineDefaults.d.ts +13 -0
- package/dist/pipeline/defaults/pipelineDefaults.d.ts.map +1 -0
- package/dist/pipeline/defaults/pipelineDefaults.js +266 -0
- package/dist/pipeline/defaults/pipelineDefaults.js.map +1 -0
- package/dist/pipeline/yaml/DedupYaml.d.ts +33 -0
- package/dist/pipeline/yaml/DedupYaml.d.ts.map +1 -0
- package/dist/pipeline/yaml/DedupYaml.js +25 -0
- package/dist/pipeline/yaml/DedupYaml.js.map +1 -0
- package/dist/pipeline/yaml/GroupingYaml.d.ts +49 -0
- package/dist/pipeline/yaml/GroupingYaml.d.ts.map +1 -0
- package/dist/pipeline/yaml/GroupingYaml.js +39 -0
- package/dist/pipeline/yaml/GroupingYaml.js.map +1 -0
- package/dist/pipeline/yaml/NormalizationYaml.d.ts +54 -0
- package/dist/pipeline/yaml/NormalizationYaml.d.ts.map +1 -0
- package/dist/pipeline/yaml/NormalizationYaml.js +23 -0
- package/dist/pipeline/yaml/NormalizationYaml.js.map +1 -0
- package/dist/pipeline/yaml/pipelineYaml.d.ts +11 -0
- package/dist/pipeline/yaml/pipelineYaml.d.ts.map +1 -0
- package/dist/pipeline/yaml/pipelineYaml.js +49 -0
- package/dist/pipeline/yaml/pipelineYaml.js.map +1 -0
- package/dist/realtime/events.d.ts +11 -0
- package/dist/realtime/events.d.ts.map +1 -0
- package/dist/realtime/events.js +21 -0
- package/dist/realtime/events.js.map +1 -0
- package/dist/routes/alert.routes.d.ts +4 -0
- package/dist/routes/alert.routes.d.ts.map +1 -0
- package/dist/routes/alert.routes.js +15 -0
- package/dist/routes/alert.routes.js.map +1 -0
- package/dist/routes/dedup-config.routes.d.ts +4 -0
- package/dist/routes/dedup-config.routes.d.ts.map +1 -0
- package/dist/routes/dedup-config.routes.js +82 -0
- package/dist/routes/dedup-config.routes.js.map +1 -0
- package/dist/routes/grouping-config.routes.d.ts +4 -0
- package/dist/routes/grouping-config.routes.d.ts.map +1 -0
- package/dist/routes/grouping-config.routes.js +82 -0
- package/dist/routes/grouping-config.routes.js.map +1 -0
- package/dist/routes/incident.routes.d.ts +4 -0
- package/dist/routes/incident.routes.d.ts.map +1 -0
- package/dist/routes/incident.routes.js +21 -0
- package/dist/routes/incident.routes.js.map +1 -0
- package/dist/routes/index.d.ts +47 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +83 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/normalization-config.routes.d.ts +4 -0
- package/dist/routes/normalization-config.routes.d.ts.map +1 -0
- package/dist/routes/normalization-config.routes.js +199 -0
- package/dist/routes/normalization-config.routes.js.map +1 -0
- package/dist/routes/notification-provider.routes.d.ts +4 -0
- package/dist/routes/notification-provider.routes.d.ts.map +1 -0
- package/dist/routes/notification-provider.routes.js +13 -0
- package/dist/routes/notification-provider.routes.js.map +1 -0
- package/dist/routes/pipeline.routes.d.ts +8 -0
- package/dist/routes/pipeline.routes.d.ts.map +1 -0
- package/dist/routes/pipeline.routes.js +243 -0
- package/dist/routes/pipeline.routes.js.map +1 -0
- package/dist/routes/settings.routes.d.ts +4 -0
- package/dist/routes/settings.routes.d.ts.map +1 -0
- package/dist/routes/settings.routes.js +10 -0
- package/dist/routes/settings.routes.js.map +1 -0
- package/dist/routes/sop.routes.d.ts +4 -0
- package/dist/routes/sop.routes.d.ts.map +1 -0
- package/dist/routes/sop.routes.js +14 -0
- package/dist/routes/sop.routes.js.map +1 -0
- package/dist/routes/source.routes.d.ts +9 -0
- package/dist/routes/source.routes.d.ts.map +1 -0
- package/dist/routes/source.routes.js +31 -0
- package/dist/routes/source.routes.js.map +1 -0
- package/dist/routes/tenant.routes.d.ts +4 -0
- package/dist/routes/tenant.routes.d.ts.map +1 -0
- package/dist/routes/tenant.routes.js +10 -0
- package/dist/routes/tenant.routes.js.map +1 -0
- package/dist/routes/workflow.routes.d.ts +4 -0
- package/dist/routes/workflow.routes.d.ts.map +1 -0
- package/dist/routes/workflow.routes.js +18 -0
- package/dist/routes/workflow.routes.js.map +1 -0
- package/dist/server.d.ts +22 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +76 -0
- package/dist/server.js.map +1 -0
- package/dist/service.d.ts +159 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +156 -0
- package/dist/service.js.map +1 -0
- package/dist/services/alert.service.d.ts +76 -0
- package/dist/services/alert.service.d.ts.map +1 -0
- package/dist/services/alert.service.js +688 -0
- package/dist/services/alert.service.js.map +1 -0
- package/dist/services/connector.service.d.ts +65 -0
- package/dist/services/connector.service.d.ts.map +1 -0
- package/dist/services/connector.service.js +28 -0
- package/dist/services/connector.service.js.map +1 -0
- package/dist/services/incident.service.d.ts +108 -0
- package/dist/services/incident.service.d.ts.map +1 -0
- package/dist/services/incident.service.js +325 -0
- package/dist/services/incident.service.js.map +1 -0
- package/dist/services/notification-provider.service.d.ts +12 -0
- package/dist/services/notification-provider.service.d.ts.map +1 -0
- package/dist/services/notification-provider.service.js +25 -0
- package/dist/services/notification-provider.service.js.map +1 -0
- package/dist/services/settings.service.d.ts +8 -0
- package/dist/services/settings.service.d.ts.map +1 -0
- package/dist/services/settings.service.js +14 -0
- package/dist/services/settings.service.js.map +1 -0
- package/dist/services/sop.service.d.ts +60 -0
- package/dist/services/sop.service.d.ts.map +1 -0
- package/dist/services/sop.service.js +66 -0
- package/dist/services/sop.service.js.map +1 -0
- package/dist/services/source.service.d.ts +162 -0
- package/dist/services/source.service.d.ts.map +1 -0
- package/dist/services/source.service.js +124 -0
- package/dist/services/source.service.js.map +1 -0
- package/dist/services/tenant.service.d.ts +11 -0
- package/dist/services/tenant.service.d.ts.map +1 -0
- package/dist/services/tenant.service.js +22 -0
- package/dist/services/tenant.service.js.map +1 -0
- package/dist/services/workflow.service.d.ts +32 -0
- package/dist/services/workflow.service.d.ts.map +1 -0
- package/dist/services/workflow.service.js +291 -0
- package/dist/services/workflow.service.js.map +1 -0
- package/dist/standalone.d.ts +2 -0
- package/dist/standalone.d.ts.map +1 -0
- package/dist/standalone.js +55 -0
- package/dist/standalone.js.map +1 -0
- package/dist/tenancy.d.ts +5 -0
- package/dist/tenancy.d.ts.map +1 -0
- package/dist/tenancy.js +35 -0
- package/dist/tenancy.js.map +1 -0
- package/dist/utils/notificationTemplates.d.ts +98 -0
- package/dist/utils/notificationTemplates.d.ts.map +1 -0
- package/dist/utils/notificationTemplates.js +227 -0
- package/dist/utils/notificationTemplates.js.map +1 -0
- package/dist/utils/secretCrypto.d.ts +3 -0
- package/dist/utils/secretCrypto.d.ts.map +1 -0
- package/dist/utils/secretCrypto.js +40 -0
- package/dist/utils/secretCrypto.js.map +1 -0
- package/dist/utils/workflowYaml.d.ts +53 -0
- package/dist/utils/workflowYaml.d.ts.map +1 -0
- package/dist/utils/workflowYaml.js +269 -0
- package/dist/utils/workflowYaml.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,1262 @@
|
|
|
1
|
+
import { sql } from "drizzle-orm";
|
|
2
|
+
import yaml from "js-yaml";
|
|
3
|
+
/**
|
|
4
|
+
* Run all DDL migrations for the Insight plugin.
|
|
5
|
+
* Safe to run on every start - all statements use IF NOT EXISTS / IF EXISTS guards.
|
|
6
|
+
*/
|
|
7
|
+
export async function runMigrations(db) {
|
|
8
|
+
const defaultTenantId = (process.env.INSIGHT_DEFAULT_TENANT_ID || "default").trim() || "default";
|
|
9
|
+
const defaultTenantSql = defaultTenantId.replace(/'/g, "''");
|
|
10
|
+
const defaultTokenTtlDaysRaw = Number.parseInt(process.env.INSIGHT_WEBHOOK_TOKEN_DEFAULT_DAYS || "30", 10);
|
|
11
|
+
const defaultTokenTtlDays = Number.isFinite(defaultTokenTtlDaysRaw) && defaultTokenTtlDaysRaw > 0
|
|
12
|
+
? defaultTokenTtlDaysRaw
|
|
13
|
+
: 30;
|
|
14
|
+
// Rename tables and columns if they exist from the old 'connector' naming convention
|
|
15
|
+
await db.execute(sql.raw(`
|
|
16
|
+
DO $$
|
|
17
|
+
BEGIN
|
|
18
|
+
-- Rename main table
|
|
19
|
+
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'meyiconnect' AND table_name = 'insight_connectors') THEN
|
|
20
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'meyiconnect' AND table_name = 'insight_sources') THEN
|
|
21
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_connectors" RENAME TO "insight_sources"';
|
|
22
|
+
END IF;
|
|
23
|
+
END IF;
|
|
24
|
+
|
|
25
|
+
-- Rename CloudWatch setups
|
|
26
|
+
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'meyiconnect' AND table_name = 'insight_cloudwatch_connector_setups') THEN
|
|
27
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'meyiconnect' AND table_name = 'insight_cloudwatch_source_setups') THEN
|
|
28
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_cloudwatch_connector_setups" RENAME TO "insight_cloudwatch_source_setups"';
|
|
29
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_cloudwatch_source_setups" RENAME COLUMN "connector_id" TO "source_id"';
|
|
30
|
+
END IF;
|
|
31
|
+
END IF;
|
|
32
|
+
|
|
33
|
+
-- Rename CloudTrail setups
|
|
34
|
+
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'meyiconnect' AND table_name = 'insight_cloudtrail_connector_setups') THEN
|
|
35
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'meyiconnect' AND table_name = 'insight_cloudtrail_source_setups') THEN
|
|
36
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_cloudtrail_connector_setups" RENAME TO "insight_cloudtrail_source_setups"';
|
|
37
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_cloudtrail_source_setups" RENAME COLUMN "connector_id" TO "source_id"';
|
|
38
|
+
END IF;
|
|
39
|
+
END IF;
|
|
40
|
+
|
|
41
|
+
-- Rename Grafana setups
|
|
42
|
+
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'meyiconnect' AND table_name = 'insight_grafana_connector_setups') THEN
|
|
43
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'meyiconnect' AND table_name = 'insight_grafana_source_setups') THEN
|
|
44
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_grafana_connector_setups" RENAME TO "insight_grafana_source_setups"';
|
|
45
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_grafana_source_setups" RENAME COLUMN "connector_id" TO "source_id"';
|
|
46
|
+
END IF;
|
|
47
|
+
END IF;
|
|
48
|
+
|
|
49
|
+
-- Rename Prometheus setups
|
|
50
|
+
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'meyiconnect' AND table_name = 'insight_prometheus_connector_setups') THEN
|
|
51
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'meyiconnect' AND table_name = 'insight_prometheus_source_setups') THEN
|
|
52
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_prometheus_connector_setups" RENAME TO "insight_prometheus_source_setups"';
|
|
53
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_prometheus_source_setups" RENAME COLUMN "connector_id" TO "source_id"';
|
|
54
|
+
END IF;
|
|
55
|
+
END IF;
|
|
56
|
+
|
|
57
|
+
-- Rename Connector Health
|
|
58
|
+
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'meyiconnect' AND table_name = 'insight_connector_health') THEN
|
|
59
|
+
IF NOT EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'meyiconnect' AND table_name = 'insight_source_health') THEN
|
|
60
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_connector_health" RENAME TO "insight_source_health"';
|
|
61
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_source_health" RENAME COLUMN "connector_id" TO "source_id"';
|
|
62
|
+
END IF;
|
|
63
|
+
END IF;
|
|
64
|
+
|
|
65
|
+
-- Rename Webhook Failure Logs
|
|
66
|
+
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'meyiconnect' AND table_name = 'insight_webhook_failure_logs' AND column_name = 'connector_id') THEN
|
|
67
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_webhook_failure_logs" RENAME COLUMN "connector_id" TO "source_id"';
|
|
68
|
+
END IF;
|
|
69
|
+
|
|
70
|
+
-- Rename columns in alerts
|
|
71
|
+
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'meyiconnect' AND table_name = 'insight_alerts' AND column_name = 'connector_id') THEN
|
|
72
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_alerts" RENAME COLUMN "connector_id" TO "source_id"';
|
|
73
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_alerts" RENAME COLUMN "connector_name" TO "source_name"';
|
|
74
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_alerts" RENAME COLUMN "connector_type" TO "source_type"';
|
|
75
|
+
END IF;
|
|
76
|
+
|
|
77
|
+
-- Rename columns in configs
|
|
78
|
+
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'meyiconnect' AND table_name = 'insight_normalization_configs' AND column_name = 'connector_id') THEN
|
|
79
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_normalization_configs" RENAME COLUMN "connector_id" TO "source_id"';
|
|
80
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_normalization_configs" RENAME COLUMN "connector_type" TO "source_type"';
|
|
81
|
+
END IF;
|
|
82
|
+
|
|
83
|
+
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'meyiconnect' AND table_name = 'insight_dedup_configs' AND column_name = 'connector_id') THEN
|
|
84
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_dedup_configs" RENAME COLUMN "connector_id" TO "source_id"';
|
|
85
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_dedup_configs" RENAME COLUMN "connector_type" TO "source_type"';
|
|
86
|
+
END IF;
|
|
87
|
+
|
|
88
|
+
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'meyiconnect' AND table_name = 'insight_grouping_configs' AND column_name = 'connector_id') THEN
|
|
89
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_grouping_configs" RENAME COLUMN "connector_id" TO "source_id"';
|
|
90
|
+
EXECUTE 'ALTER TABLE "meyiconnect"."insight_grouping_configs" RENAME COLUMN "connector_type" TO "source_type"';
|
|
91
|
+
END IF;
|
|
92
|
+
|
|
93
|
+
END $$;
|
|
94
|
+
`));
|
|
95
|
+
await db.execute(sql.raw(`
|
|
96
|
+
DO $$
|
|
97
|
+
DECLARE
|
|
98
|
+
v_relkind "char";
|
|
99
|
+
BEGIN
|
|
100
|
+
SELECT c.relkind INTO v_relkind
|
|
101
|
+
FROM pg_class c
|
|
102
|
+
JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
103
|
+
WHERE n.nspname = 'meyiconnect' AND c.relname = 'insight_tenants'
|
|
104
|
+
LIMIT 1;
|
|
105
|
+
|
|
106
|
+
IF v_relkind IS NULL THEN
|
|
107
|
+
CREATE TABLE "meyiconnect"."insight_tenants" (
|
|
108
|
+
"id" TEXT PRIMARY KEY,
|
|
109
|
+
"name" TEXT NOT NULL,
|
|
110
|
+
"is_default" BOOLEAN NOT NULL DEFAULT false,
|
|
111
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
112
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
113
|
+
);
|
|
114
|
+
INSERT INTO "meyiconnect"."insight_tenants" ("id", "name", "is_default")
|
|
115
|
+
VALUES ('${defaultTenantSql}', 'Default tenant', true)
|
|
116
|
+
ON CONFLICT ("id") DO UPDATE SET "is_default" = true, "updated_at" = NOW();
|
|
117
|
+
ELSIF v_relkind = 'r' THEN
|
|
118
|
+
INSERT INTO "meyiconnect"."insight_tenants" ("id", "name", "is_default")
|
|
119
|
+
VALUES ('${defaultTenantSql}', 'Default tenant', true)
|
|
120
|
+
ON CONFLICT ("id") DO UPDATE SET "is_default" = true, "updated_at" = NOW();
|
|
121
|
+
END IF;
|
|
122
|
+
END $$;
|
|
123
|
+
`));
|
|
124
|
+
// insight_sources
|
|
125
|
+
await db.execute(sql.raw(`
|
|
126
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_sources" (
|
|
127
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
128
|
+
"name" TEXT NOT NULL,
|
|
129
|
+
"type" TEXT NOT NULL,
|
|
130
|
+
"webhook_token" TEXT NOT NULL,
|
|
131
|
+
"webhook_auth_token" TEXT,
|
|
132
|
+
"webhook_token_never_expires" BOOLEAN NOT NULL DEFAULT false,
|
|
133
|
+
"webhook_token_expires_at" TIMESTAMPTZ,
|
|
134
|
+
"is_active" BOOLEAN NOT NULL DEFAULT true,
|
|
135
|
+
"description" TEXT,
|
|
136
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
137
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
138
|
+
)
|
|
139
|
+
`));
|
|
140
|
+
await db.execute(sql.raw(`
|
|
141
|
+
DO $$
|
|
142
|
+
BEGIN
|
|
143
|
+
IF EXISTS (
|
|
144
|
+
SELECT 1 FROM information_schema.columns
|
|
145
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_sources' AND column_name = 'tenant_id' AND data_type = 'uuid'
|
|
146
|
+
) THEN
|
|
147
|
+
ALTER TABLE "meyiconnect"."insight_sources" ALTER COLUMN "tenant_id" TYPE TEXT USING "tenant_id"::TEXT;
|
|
148
|
+
ELSIF NOT EXISTS (
|
|
149
|
+
SELECT 1 FROM information_schema.columns
|
|
150
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_sources' AND column_name = 'tenant_id'
|
|
151
|
+
) THEN
|
|
152
|
+
ALTER TABLE "meyiconnect"."insight_sources" ADD COLUMN "tenant_id" TEXT;
|
|
153
|
+
END IF;
|
|
154
|
+
END $$;
|
|
155
|
+
`));
|
|
156
|
+
await db.execute(sql.raw(`UPDATE "meyiconnect"."insight_sources" SET "tenant_id" = '${defaultTenantSql}' WHERE "tenant_id" IS NULL OR "tenant_id"::text = ''`));
|
|
157
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_sources_tenant_id_idx ON "meyiconnect"."insight_sources" ("tenant_id")`));
|
|
158
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sources" ADD COLUMN IF NOT EXISTS "webhook_token_never_expires" BOOLEAN NOT NULL DEFAULT false`));
|
|
159
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sources" ADD COLUMN IF NOT EXISTS "webhook_token_expires_at" TIMESTAMPTZ`));
|
|
160
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sources" ADD COLUMN IF NOT EXISTS "is_active" BOOLEAN NOT NULL DEFAULT true`));
|
|
161
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sources" ADD COLUMN IF NOT EXISTS "description" TEXT`));
|
|
162
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sources" ALTER COLUMN "webhook_token_expires_at" SET DEFAULT (NOW() + INTERVAL '${defaultTokenTtlDays} days')`));
|
|
163
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sources" DROP COLUMN IF EXISTS "config"`));
|
|
164
|
+
await db.execute(sql.raw(`
|
|
165
|
+
UPDATE "meyiconnect"."insight_sources"
|
|
166
|
+
SET "webhook_token" = gen_random_uuid()::TEXT
|
|
167
|
+
WHERE "webhook_token" IS NULL
|
|
168
|
+
`));
|
|
169
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sources" ALTER COLUMN "webhook_token" SET NOT NULL`)).catch(() => { });
|
|
170
|
+
await db.execute(sql.raw(`
|
|
171
|
+
UPDATE "meyiconnect"."insight_sources"
|
|
172
|
+
SET "webhook_token_expires_at" = NOW() + INTERVAL '${defaultTokenTtlDays} days'
|
|
173
|
+
WHERE COALESCE("webhook_token_never_expires", FALSE) = FALSE
|
|
174
|
+
AND "webhook_token_expires_at" IS NULL
|
|
175
|
+
`));
|
|
176
|
+
await db.execute(sql.raw(`
|
|
177
|
+
CREATE UNIQUE INDEX IF NOT EXISTS insight_sources_webhook_token_unique
|
|
178
|
+
ON "meyiconnect"."insight_sources" ("webhook_token")
|
|
179
|
+
`));
|
|
180
|
+
// CloudWatch source setup lives in a dedicated one-to-one table.
|
|
181
|
+
await db.execute(sql.raw(`
|
|
182
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_cloudwatch_source_setups" (
|
|
183
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
184
|
+
"source_id" UUID NOT NULL REFERENCES "meyiconnect"."insight_sources"("id") ON DELETE CASCADE,
|
|
185
|
+
"aws_access_key_id" TEXT,
|
|
186
|
+
"aws_secret_access_key" TEXT,
|
|
187
|
+
"aws_session_token" TEXT,
|
|
188
|
+
"aws_region" TEXT,
|
|
189
|
+
"aws_stack_name" TEXT,
|
|
190
|
+
"aws_lambda_name" TEXT,
|
|
191
|
+
"aws_alarm_name_prefix" TEXT,
|
|
192
|
+
"aws_selected_alarm_names" JSONB DEFAULT '[]',
|
|
193
|
+
"aws_selected_metric_keys" JSONB DEFAULT '[]',
|
|
194
|
+
"aws_deployment_status" TEXT NOT NULL DEFAULT 'not_started',
|
|
195
|
+
"aws_deployment_status_reason" TEXT,
|
|
196
|
+
"aws_stack_id" TEXT,
|
|
197
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
198
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
199
|
+
)
|
|
200
|
+
`));
|
|
201
|
+
await db.execute(sql.raw(`CREATE UNIQUE INDEX IF NOT EXISTS insight_cloudwatch_source_setups_source_unique ON "meyiconnect"."insight_cloudwatch_source_setups" ("source_id")`));
|
|
202
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_cloudwatch_source_setups_status_idx ON "meyiconnect"."insight_cloudwatch_source_setups" ("aws_deployment_status")`));
|
|
203
|
+
// CloudTrail source setup — dedicated one-to-one side-table (same pattern as cloudwatch).
|
|
204
|
+
await db.execute(sql.raw(`
|
|
205
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_cloudtrail_source_setups" (
|
|
206
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
207
|
+
"source_id" UUID NOT NULL REFERENCES "meyiconnect"."insight_sources"("id") ON DELETE CASCADE,
|
|
208
|
+
"aws_region" TEXT,
|
|
209
|
+
"aws_stack_name" TEXT,
|
|
210
|
+
"aws_create_new_trail" BOOLEAN NOT NULL DEFAULT true,
|
|
211
|
+
"aws_deployment_status" TEXT NOT NULL DEFAULT 'not_started',
|
|
212
|
+
"aws_deployment_status_reason" TEXT,
|
|
213
|
+
"aws_stack_id" TEXT,
|
|
214
|
+
"aws_deployment_mode" TEXT DEFAULT 'Organizations',
|
|
215
|
+
"aws_target_ous" TEXT,
|
|
216
|
+
"aws_target_accounts" TEXT,
|
|
217
|
+
"aws_target_regions" TEXT,
|
|
218
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
219
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
220
|
+
)
|
|
221
|
+
`));
|
|
222
|
+
await db.execute(sql.raw(`CREATE UNIQUE INDEX IF NOT EXISTS insight_cloudtrail_source_setups_source_unique ON "meyiconnect"."insight_cloudtrail_source_setups" ("source_id")`));
|
|
223
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_cloudtrail_source_setups_status_idx ON "meyiconnect"."insight_cloudtrail_source_setups" ("aws_deployment_status")`));
|
|
224
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_cloudtrail_source_setups" ADD COLUMN IF NOT EXISTS "aws_create_new_trail" BOOLEAN NOT NULL DEFAULT true`));
|
|
225
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_cloudtrail_source_setups" ADD COLUMN IF NOT EXISTS "aws_deployment_mode" TEXT DEFAULT 'Organizations'`));
|
|
226
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_cloudtrail_source_setups" ADD COLUMN IF NOT EXISTS "aws_target_ous" TEXT`));
|
|
227
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_cloudtrail_source_setups" ADD COLUMN IF NOT EXISTS "aws_target_accounts" TEXT`));
|
|
228
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_cloudtrail_source_setups" ADD COLUMN IF NOT EXISTS "aws_target_regions" TEXT`));
|
|
229
|
+
await db.execute(sql.raw(`
|
|
230
|
+
DO $$
|
|
231
|
+
BEGIN
|
|
232
|
+
IF EXISTS (
|
|
233
|
+
SELECT 1
|
|
234
|
+
FROM information_schema.columns
|
|
235
|
+
WHERE table_schema = 'meyiconnect'
|
|
236
|
+
AND table_name = 'insight_sources'
|
|
237
|
+
AND column_name = 'aws_region'
|
|
238
|
+
) THEN
|
|
239
|
+
INSERT INTO "meyiconnect"."insight_cloudwatch_source_setups" (
|
|
240
|
+
"source_id",
|
|
241
|
+
"aws_access_key_id",
|
|
242
|
+
"aws_secret_access_key",
|
|
243
|
+
"aws_session_token",
|
|
244
|
+
"aws_region",
|
|
245
|
+
"aws_stack_name",
|
|
246
|
+
"aws_lambda_name",
|
|
247
|
+
"aws_alarm_name_prefix",
|
|
248
|
+
"aws_selected_alarm_names",
|
|
249
|
+
"aws_selected_metric_keys",
|
|
250
|
+
"aws_deployment_status",
|
|
251
|
+
"aws_deployment_status_reason",
|
|
252
|
+
"aws_stack_id",
|
|
253
|
+
"created_at",
|
|
254
|
+
"updated_at"
|
|
255
|
+
)
|
|
256
|
+
SELECT
|
|
257
|
+
"id",
|
|
258
|
+
"aws_access_key_id",
|
|
259
|
+
"aws_secret_access_key",
|
|
260
|
+
"aws_session_token",
|
|
261
|
+
"aws_region",
|
|
262
|
+
"aws_stack_name",
|
|
263
|
+
"aws_lambda_name",
|
|
264
|
+
"aws_alarm_name_prefix",
|
|
265
|
+
COALESCE("aws_selected_alarm_names", '[]'::jsonb),
|
|
266
|
+
COALESCE("aws_selected_metric_keys", '[]'::jsonb),
|
|
267
|
+
COALESCE("aws_deployment_status", 'not_started'),
|
|
268
|
+
"aws_deployment_status_reason",
|
|
269
|
+
"aws_stack_id",
|
|
270
|
+
NOW(),
|
|
271
|
+
NOW()
|
|
272
|
+
FROM "meyiconnect"."insight_sources"
|
|
273
|
+
WHERE "type" = 'cloudwatch'
|
|
274
|
+
AND (
|
|
275
|
+
"aws_access_key_id" IS NOT NULL OR
|
|
276
|
+
"aws_secret_access_key" IS NOT NULL OR
|
|
277
|
+
"aws_session_token" IS NOT NULL OR
|
|
278
|
+
"aws_region" IS NOT NULL OR
|
|
279
|
+
"aws_stack_name" IS NOT NULL OR
|
|
280
|
+
"aws_lambda_name" IS NOT NULL OR
|
|
281
|
+
"aws_alarm_name_prefix" IS NOT NULL OR
|
|
282
|
+
"aws_deployment_status" IS NOT NULL OR
|
|
283
|
+
"aws_stack_id" IS NOT NULL
|
|
284
|
+
)
|
|
285
|
+
ON CONFLICT ("source_id") DO UPDATE SET
|
|
286
|
+
"aws_access_key_id" = EXCLUDED."aws_access_key_id",
|
|
287
|
+
"aws_secret_access_key" = EXCLUDED."aws_secret_access_key",
|
|
288
|
+
"aws_session_token" = EXCLUDED."aws_session_token",
|
|
289
|
+
"aws_region" = EXCLUDED."aws_region",
|
|
290
|
+
"aws_stack_name" = EXCLUDED."aws_stack_name",
|
|
291
|
+
"aws_lambda_name" = EXCLUDED."aws_lambda_name",
|
|
292
|
+
"aws_alarm_name_prefix" = EXCLUDED."aws_alarm_name_prefix",
|
|
293
|
+
"aws_selected_alarm_names" = EXCLUDED."aws_selected_alarm_names",
|
|
294
|
+
"aws_selected_metric_keys" = EXCLUDED."aws_selected_metric_keys",
|
|
295
|
+
"aws_deployment_status" = EXCLUDED."aws_deployment_status",
|
|
296
|
+
"aws_deployment_status_reason" = EXCLUDED."aws_deployment_status_reason",
|
|
297
|
+
"aws_stack_id" = EXCLUDED."aws_stack_id",
|
|
298
|
+
"updated_at" = NOW();
|
|
299
|
+
END IF;
|
|
300
|
+
END $$;
|
|
301
|
+
`));
|
|
302
|
+
await db.execute(sql.raw(`
|
|
303
|
+
ALTER TABLE "meyiconnect"."insight_sources"
|
|
304
|
+
DROP COLUMN IF EXISTS "aws_access_key_id",
|
|
305
|
+
DROP COLUMN IF EXISTS "aws_secret_access_key",
|
|
306
|
+
DROP COLUMN IF EXISTS "aws_session_token",
|
|
307
|
+
DROP COLUMN IF EXISTS "aws_region",
|
|
308
|
+
DROP COLUMN IF EXISTS "aws_stack_name",
|
|
309
|
+
DROP COLUMN IF EXISTS "aws_lambda_name",
|
|
310
|
+
DROP COLUMN IF EXISTS "aws_alarm_name_prefix",
|
|
311
|
+
DROP COLUMN IF EXISTS "aws_selected_alarm_names",
|
|
312
|
+
DROP COLUMN IF EXISTS "aws_selected_metric_keys",
|
|
313
|
+
DROP COLUMN IF EXISTS "aws_deployment_status",
|
|
314
|
+
DROP COLUMN IF EXISTS "aws_deployment_status_reason",
|
|
315
|
+
DROP COLUMN IF EXISTS "aws_stack_id"
|
|
316
|
+
`));
|
|
317
|
+
// Grafana source setup lives in a dedicated one-to-one table.
|
|
318
|
+
await db.execute(sql.raw(`
|
|
319
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_grafana_source_setups" (
|
|
320
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
321
|
+
"source_id" UUID NOT NULL REFERENCES "meyiconnect"."insight_sources"("id") ON DELETE CASCADE,
|
|
322
|
+
"grafana_base_url" TEXT,
|
|
323
|
+
"grafana_contact_point_name" TEXT,
|
|
324
|
+
"grafana_account_token_encrypted" TEXT,
|
|
325
|
+
"grafana_auto_route" BOOLEAN NOT NULL DEFAULT false,
|
|
326
|
+
"grafana_matcher_label" TEXT,
|
|
327
|
+
"grafana_matcher_value" TEXT,
|
|
328
|
+
"grafana_policy_updated" BOOLEAN NOT NULL DEFAULT false,
|
|
329
|
+
"grafana_setup_status" TEXT NOT NULL DEFAULT 'not_started',
|
|
330
|
+
"grafana_setup_status_reason" TEXT,
|
|
331
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
332
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
333
|
+
)
|
|
334
|
+
`));
|
|
335
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_grafana_source_setups" ADD COLUMN IF NOT EXISTS "grafana_account_token_encrypted" TEXT`));
|
|
336
|
+
await db.execute(sql.raw(`CREATE UNIQUE INDEX IF NOT EXISTS insight_grafana_source_setups_source_unique ON "meyiconnect"."insight_grafana_source_setups" ("source_id")`));
|
|
337
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_grafana_source_setups_status_idx ON "meyiconnect"."insight_grafana_source_setups" ("grafana_setup_status")`));
|
|
338
|
+
// Prometheus source setup lives in a dedicated one-to-one table.
|
|
339
|
+
await db.execute(sql.raw(`
|
|
340
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_prometheus_source_setups" (
|
|
341
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
342
|
+
"source_id" UUID NOT NULL REFERENCES "meyiconnect"."insight_sources"("id") ON DELETE CASCADE,
|
|
343
|
+
"prometheus_environment" TEXT,
|
|
344
|
+
"prometheus_receiver_name" TEXT,
|
|
345
|
+
"prometheus_base_url" TEXT,
|
|
346
|
+
"alertmanager_base_url" TEXT,
|
|
347
|
+
"prometheus_setup_status" TEXT NOT NULL DEFAULT 'not_started',
|
|
348
|
+
"prometheus_setup_status_reason" TEXT,
|
|
349
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
350
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
351
|
+
)
|
|
352
|
+
`));
|
|
353
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_prometheus_source_setups" ADD COLUMN IF NOT EXISTS "prometheus_base_url" TEXT`));
|
|
354
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_prometheus_source_setups" ADD COLUMN IF NOT EXISTS "alertmanager_base_url" TEXT`));
|
|
355
|
+
await db.execute(sql.raw(`CREATE UNIQUE INDEX IF NOT EXISTS insight_prometheus_source_setups_source_unique ON "meyiconnect"."insight_prometheus_source_setups" ("source_id")`));
|
|
356
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_prometheus_source_setups_status_idx ON "meyiconnect"."insight_prometheus_source_setups" ("prometheus_setup_status")`));
|
|
357
|
+
// Source observability: one health row per source + failed webhook log.
|
|
358
|
+
await db.execute(sql.raw(`
|
|
359
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_source_health" (
|
|
360
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
361
|
+
"source_id" UUID NOT NULL REFERENCES "meyiconnect"."insight_sources"("id") ON DELETE CASCADE,
|
|
362
|
+
"delivery_status" TEXT NOT NULL DEFAULT 'unknown',
|
|
363
|
+
"last_webhook_received_at" TIMESTAMPTZ,
|
|
364
|
+
"last_successful_webhook_at" TIMESTAMPTZ,
|
|
365
|
+
"last_failed_webhook_at" TIMESTAMPTZ,
|
|
366
|
+
"last_error_code" TEXT,
|
|
367
|
+
"last_error_message" TEXT,
|
|
368
|
+
"last_alert_id" UUID,
|
|
369
|
+
"success_count" INTEGER NOT NULL DEFAULT 0,
|
|
370
|
+
"failure_count" INTEGER NOT NULL DEFAULT 0,
|
|
371
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
372
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
373
|
+
)
|
|
374
|
+
`));
|
|
375
|
+
await db.execute(sql.raw(`CREATE UNIQUE INDEX IF NOT EXISTS insight_source_health_source_unique ON "meyiconnect"."insight_source_health" ("source_id")`));
|
|
376
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_source_health_status_idx ON "meyiconnect"."insight_source_health" ("delivery_status")`));
|
|
377
|
+
await db.execute(sql.raw(`
|
|
378
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_webhook_failure_logs" (
|
|
379
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
380
|
+
"source_id" UUID REFERENCES "meyiconnect"."insight_sources"("id") ON DELETE SET NULL,
|
|
381
|
+
"token_hash" TEXT,
|
|
382
|
+
"token_preview" TEXT,
|
|
383
|
+
"error_code" TEXT NOT NULL,
|
|
384
|
+
"error_message" TEXT NOT NULL,
|
|
385
|
+
"request_ip" TEXT,
|
|
386
|
+
"user_agent" TEXT,
|
|
387
|
+
"method" TEXT,
|
|
388
|
+
"path" TEXT,
|
|
389
|
+
"payload" JSONB,
|
|
390
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
391
|
+
)
|
|
392
|
+
`));
|
|
393
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_webhook_failure_logs_source_idx ON "meyiconnect"."insight_webhook_failure_logs" ("source_id")`));
|
|
394
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_webhook_failure_logs_error_idx ON "meyiconnect"."insight_webhook_failure_logs" ("error_code")`));
|
|
395
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_webhook_failure_logs_created_idx ON "meyiconnect"."insight_webhook_failure_logs" ("created_at")`));
|
|
396
|
+
// insight_projects
|
|
397
|
+
await db.execute(sql.raw(`
|
|
398
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_projects" (
|
|
399
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
400
|
+
"name" TEXT NOT NULL,
|
|
401
|
+
"tag" TEXT NOT NULL,
|
|
402
|
+
"description" TEXT,
|
|
403
|
+
"dependencies" JSONB DEFAULT '[]',
|
|
404
|
+
"aws_access_key_id" TEXT,
|
|
405
|
+
"aws_secret_access_key" TEXT,
|
|
406
|
+
"aws_region" TEXT,
|
|
407
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
408
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
409
|
+
)
|
|
410
|
+
`));
|
|
411
|
+
await db.execute(sql.raw(`
|
|
412
|
+
DO $$
|
|
413
|
+
BEGIN
|
|
414
|
+
IF EXISTS (
|
|
415
|
+
SELECT 1 FROM information_schema.columns
|
|
416
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_projects' AND column_name = 'tenant_id' AND data_type = 'uuid'
|
|
417
|
+
) THEN
|
|
418
|
+
ALTER TABLE "meyiconnect"."insight_projects" ALTER COLUMN "tenant_id" TYPE TEXT USING "tenant_id"::TEXT;
|
|
419
|
+
ELSIF NOT EXISTS (
|
|
420
|
+
SELECT 1 FROM information_schema.columns
|
|
421
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_projects' AND column_name = 'tenant_id'
|
|
422
|
+
) THEN
|
|
423
|
+
ALTER TABLE "meyiconnect"."insight_projects" ADD COLUMN "tenant_id" TEXT;
|
|
424
|
+
END IF;
|
|
425
|
+
END $$;
|
|
426
|
+
`));
|
|
427
|
+
await db.execute(sql.raw(`
|
|
428
|
+
ALTER TABLE "meyiconnect"."insight_projects"
|
|
429
|
+
ADD COLUMN IF NOT EXISTS "aws_access_key_id" TEXT,
|
|
430
|
+
ADD COLUMN IF NOT EXISTS "aws_secret_access_key" TEXT,
|
|
431
|
+
ADD COLUMN IF NOT EXISTS "aws_region" TEXT
|
|
432
|
+
`));
|
|
433
|
+
await db.execute(sql.raw(`UPDATE "meyiconnect"."insight_projects" SET "tenant_id" = '${defaultTenantSql}' WHERE "tenant_id" IS NULL OR "tenant_id"::text = ''`));
|
|
434
|
+
await db.execute(sql.raw(`DROP INDEX IF EXISTS "meyiconnect"."insight_projects_tag_unique"`)).catch(() => { });
|
|
435
|
+
await db.execute(sql.raw(`DROP INDEX IF EXISTS insight_projects_tag_unique`)).catch(() => { });
|
|
436
|
+
await db.execute(sql.raw(`CREATE UNIQUE INDEX IF NOT EXISTS insight_projects_tenant_tag_unique ON "meyiconnect"."insight_projects" ("tenant_id", "tag")`));
|
|
437
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_projects_tag_idx ON "meyiconnect"."insight_projects" ("tag")`));
|
|
438
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_projects_tenant_id_idx ON "meyiconnect"."insight_projects" ("tenant_id")`));
|
|
439
|
+
// insight_incidents
|
|
440
|
+
await db.execute(sql.raw(`
|
|
441
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_incidents" (
|
|
442
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
443
|
+
"alias_id" SERIAL,
|
|
444
|
+
"monitor_id" TEXT,
|
|
445
|
+
"monitor_name" TEXT,
|
|
446
|
+
"monitor_type" TEXT,
|
|
447
|
+
"monitor_url" TEXT,
|
|
448
|
+
"name" TEXT NOT NULL DEFAULT '',
|
|
449
|
+
"source" TEXT NOT NULL DEFAULT '',
|
|
450
|
+
"resource_name" TEXT NOT NULL DEFAULT '',
|
|
451
|
+
"resource_type" TEXT NOT NULL DEFAULT '',
|
|
452
|
+
"down_message" TEXT,
|
|
453
|
+
"project_tag" TEXT,
|
|
454
|
+
"down_time" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
455
|
+
"incident_down_time" TEXT NOT NULL DEFAULT '',
|
|
456
|
+
"resolved_at" TIMESTAMPTZ,
|
|
457
|
+
"analysis_status" TEXT NOT NULL DEFAULT 'pending',
|
|
458
|
+
"analysis_percent" INTEGER NOT NULL DEFAULT 0,
|
|
459
|
+
"analysis_triggered_at" TIMESTAMPTZ,
|
|
460
|
+
"analysis_completed_at" TIMESTAMPTZ,
|
|
461
|
+
"analysis_result" JSONB,
|
|
462
|
+
"remediation_steps" JSONB DEFAULT '[]',
|
|
463
|
+
"confidence_score" REAL,
|
|
464
|
+
"ai_model_used" TEXT,
|
|
465
|
+
"source_alert_id" UUID,
|
|
466
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
467
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
468
|
+
)
|
|
469
|
+
`));
|
|
470
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_incidents_monitor_id_idx ON "meyiconnect"."insight_incidents" ("monitor_id")`));
|
|
471
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_incidents_status_idx ON "meyiconnect"."insight_incidents" ("analysis_status")`));
|
|
472
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "alias_id" SERIAL`));
|
|
473
|
+
await db.execute(sql.raw(`
|
|
474
|
+
DO $$
|
|
475
|
+
BEGIN
|
|
476
|
+
IF EXISTS (
|
|
477
|
+
SELECT 1 FROM information_schema.columns
|
|
478
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_incidents' AND column_name = 'tenant_id' AND data_type = 'uuid'
|
|
479
|
+
) THEN
|
|
480
|
+
ALTER TABLE "meyiconnect"."insight_incidents" ALTER COLUMN "tenant_id" TYPE TEXT USING "tenant_id"::TEXT;
|
|
481
|
+
ELSIF NOT EXISTS (
|
|
482
|
+
SELECT 1 FROM information_schema.columns
|
|
483
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_incidents' AND column_name = 'tenant_id'
|
|
484
|
+
) THEN
|
|
485
|
+
ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN "tenant_id" TEXT;
|
|
486
|
+
END IF;
|
|
487
|
+
END $$;
|
|
488
|
+
`));
|
|
489
|
+
await db.execute(sql.raw(`UPDATE "meyiconnect"."insight_incidents" SET "tenant_id" = '${defaultTenantSql}' WHERE "tenant_id" IS NULL OR "tenant_id"::text = ''`));
|
|
490
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_incidents_tenant_id_idx ON "meyiconnect"."insight_incidents" ("tenant_id")`));
|
|
491
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "incident_down_time" TEXT NOT NULL DEFAULT ''`));
|
|
492
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "name" TEXT`));
|
|
493
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "source" TEXT`));
|
|
494
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "resource_name" TEXT`));
|
|
495
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "resource_type" TEXT`));
|
|
496
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "down_time" TIMESTAMPTZ`));
|
|
497
|
+
await db.execute(sql.raw(`
|
|
498
|
+
DO $$
|
|
499
|
+
BEGIN
|
|
500
|
+
UPDATE "meyiconnect"."insight_incidents" SET "name" = COALESCE("monitor_name", 'Unknown') WHERE "name" IS NULL;
|
|
501
|
+
UPDATE "meyiconnect"."insight_incidents" SET "source" = 'Unknown' WHERE "source" IS NULL;
|
|
502
|
+
UPDATE "meyiconnect"."insight_incidents" SET "resource_name" = COALESCE("monitor_name", 'Unknown') WHERE "resource_name" IS NULL;
|
|
503
|
+
UPDATE "meyiconnect"."insight_incidents" SET "resource_type" = COALESCE("monitor_type", 'Unknown') WHERE "resource_type" IS NULL;
|
|
504
|
+
UPDATE "meyiconnect"."insight_incidents" SET "down_time" = "created_at" WHERE "down_time" IS NULL;
|
|
505
|
+
|
|
506
|
+
ALTER TABLE "meyiconnect"."insight_incidents" ALTER COLUMN "name" SET NOT NULL;
|
|
507
|
+
ALTER TABLE "meyiconnect"."insight_incidents" ALTER COLUMN "source" SET NOT NULL;
|
|
508
|
+
ALTER TABLE "meyiconnect"."insight_incidents" ALTER COLUMN "resource_name" SET NOT NULL;
|
|
509
|
+
ALTER TABLE "meyiconnect"."insight_incidents" ALTER COLUMN "resource_type" SET NOT NULL;
|
|
510
|
+
ALTER TABLE "meyiconnect"."insight_incidents" ALTER COLUMN "down_time" SET NOT NULL;
|
|
511
|
+
|
|
512
|
+
-- Remove NOT NULL from old columns if they exist
|
|
513
|
+
IF EXISTS (SELECT 1 FROM information_schema.columns WHERE table_schema = 'meyiconnect' AND table_name = 'insight_incidents' AND column_name = 'monitor_id') THEN
|
|
514
|
+
ALTER TABLE "meyiconnect"."insight_incidents" ALTER COLUMN "monitor_id" DROP NOT NULL;
|
|
515
|
+
ALTER TABLE "meyiconnect"."insight_incidents" ALTER COLUMN "monitor_name" DROP NOT NULL;
|
|
516
|
+
ALTER TABLE "meyiconnect"."insight_incidents" ALTER COLUMN "monitor_type" DROP NOT NULL;
|
|
517
|
+
END IF;
|
|
518
|
+
END $$;
|
|
519
|
+
`));
|
|
520
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "status" TEXT NOT NULL DEFAULT 'open'`));
|
|
521
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "analysis_percent" INTEGER NOT NULL DEFAULT 0`));
|
|
522
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "remediation_steps" JSONB DEFAULT '[]'`));
|
|
523
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "confidence_score" REAL`));
|
|
524
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "ai_model_used" TEXT`));
|
|
525
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "source_alert_id" UUID`));
|
|
526
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "assignee_ids" JSONB DEFAULT '[]'::jsonb`));
|
|
527
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" DROP COLUMN IF EXISTS "processing_status"`));
|
|
528
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" DROP COLUMN IF EXISTS "progress_percent"`));
|
|
529
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "account_id" TEXT`));
|
|
530
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "account_name" TEXT`));
|
|
531
|
+
await db.execute(sql.raw(`
|
|
532
|
+
UPDATE "meyiconnect"."insight_incidents" i
|
|
533
|
+
SET "account_name" = c."account_name"
|
|
534
|
+
FROM "meyiconnect"."connectors" c
|
|
535
|
+
WHERE i."account_name" IS NULL
|
|
536
|
+
AND i."account_id" IS NOT NULL
|
|
537
|
+
AND i."account_id" = c."account_id";
|
|
538
|
+
`));
|
|
539
|
+
await db.execute(sql.raw(`
|
|
540
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."incident_comments" (
|
|
541
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
542
|
+
"incident_id" UUID NOT NULL REFERENCES "meyiconnect"."insight_incidents"("id") ON DELETE CASCADE,
|
|
543
|
+
"author_id" TEXT,
|
|
544
|
+
"author_name" TEXT,
|
|
545
|
+
"message" TEXT NOT NULL,
|
|
546
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
547
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
548
|
+
)
|
|
549
|
+
`));
|
|
550
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS incident_comments_incident_id_idx ON "meyiconnect"."incident_comments" ("incident_id")`));
|
|
551
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS incident_comments_created_at_idx ON "meyiconnect"."incident_comments" ("created_at")`));
|
|
552
|
+
// insight_alerts
|
|
553
|
+
await db.execute(sql.raw(`
|
|
554
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_alerts" (
|
|
555
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
556
|
+
"tenant_id" TEXT,
|
|
557
|
+
"source_id" UUID,
|
|
558
|
+
"source_name" TEXT,
|
|
559
|
+
"source_type" TEXT,
|
|
560
|
+
"resource_id" TEXT NOT NULL,
|
|
561
|
+
"resource_name" TEXT NOT NULL,
|
|
562
|
+
"resource_type" TEXT NOT NULL,
|
|
563
|
+
"project_tag" TEXT,
|
|
564
|
+
"severity" TEXT NOT NULL DEFAULT 'high',
|
|
565
|
+
"alert_name" TEXT NOT NULL,
|
|
566
|
+
"description" TEXT,
|
|
567
|
+
"additional_configuration" JSONB,
|
|
568
|
+
"status" TEXT NOT NULL DEFAULT 'open',
|
|
569
|
+
"converted_incident_id" UUID,
|
|
570
|
+
"incident_id" UUID,
|
|
571
|
+
"alias_id" TEXT,
|
|
572
|
+
"assignee_id" UUID,
|
|
573
|
+
"down_time" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
574
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
575
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
576
|
+
"dup_count" INT NOT NULL DEFAULT 0,
|
|
577
|
+
"last_dup_at" TIMESTAMPTZ,
|
|
578
|
+
"fingerprint" TEXT,
|
|
579
|
+
"dedup_key" TEXT,
|
|
580
|
+
"pipeline_status" TEXT DEFAULT 'queued',
|
|
581
|
+
"group_id" UUID,
|
|
582
|
+
"raw_payload" JSONB
|
|
583
|
+
)
|
|
584
|
+
`));
|
|
585
|
+
await db.execute(sql.raw(`
|
|
586
|
+
DO $$
|
|
587
|
+
BEGIN
|
|
588
|
+
IF NOT EXISTS (
|
|
589
|
+
SELECT 1 FROM information_schema.columns
|
|
590
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_alerts' AND column_name = 'alert_name'
|
|
591
|
+
) THEN
|
|
592
|
+
ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN "alert_name" TEXT;
|
|
593
|
+
END IF;
|
|
594
|
+
|
|
595
|
+
IF EXISTS (
|
|
596
|
+
SELECT 1 FROM information_schema.columns
|
|
597
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_alerts' AND column_name = 'title'
|
|
598
|
+
) THEN
|
|
599
|
+
ALTER TABLE "meyiconnect"."insight_alerts" ALTER COLUMN "title" DROP NOT NULL;
|
|
600
|
+
ALTER TABLE "meyiconnect"."insight_alerts" ALTER COLUMN "title" SET DEFAULT 'Alert';
|
|
601
|
+
UPDATE "meyiconnect"."insight_alerts"
|
|
602
|
+
SET "alert_name" = COALESCE("alert_name", "title", 'Alert')
|
|
603
|
+
WHERE "alert_name" IS NULL;
|
|
604
|
+
ELSE
|
|
605
|
+
UPDATE "meyiconnect"."insight_alerts"
|
|
606
|
+
SET "alert_name" = COALESCE("alert_name", 'Alert')
|
|
607
|
+
WHERE "alert_name" IS NULL;
|
|
608
|
+
END IF;
|
|
609
|
+
|
|
610
|
+
ALTER TABLE "meyiconnect"."insight_alerts" ALTER COLUMN "alert_name" SET NOT NULL;
|
|
611
|
+
END $$;
|
|
612
|
+
`));
|
|
613
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "project_tag" TEXT`));
|
|
614
|
+
await db.execute(sql.raw(`
|
|
615
|
+
DO $$
|
|
616
|
+
BEGIN
|
|
617
|
+
IF EXISTS (
|
|
618
|
+
SELECT 1 FROM information_schema.columns
|
|
619
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_alerts' AND column_name = 'tenant_id' AND data_type = 'uuid'
|
|
620
|
+
) THEN
|
|
621
|
+
ALTER TABLE "meyiconnect"."insight_alerts" ALTER COLUMN "tenant_id" TYPE TEXT USING "tenant_id"::TEXT;
|
|
622
|
+
ELSIF NOT EXISTS (
|
|
623
|
+
SELECT 1 FROM information_schema.columns
|
|
624
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_alerts' AND column_name = 'tenant_id'
|
|
625
|
+
) THEN
|
|
626
|
+
ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN "tenant_id" TEXT;
|
|
627
|
+
END IF;
|
|
628
|
+
END $$;
|
|
629
|
+
`));
|
|
630
|
+
await db.execute(sql.raw(`UPDATE "meyiconnect"."insight_alerts" SET "tenant_id" = '${defaultTenantSql}' WHERE "tenant_id" IS NULL OR "tenant_id"::text = ''`));
|
|
631
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_alerts_tenant_id_idx ON "meyiconnect"."insight_alerts" ("tenant_id")`));
|
|
632
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "alias_id" TEXT`));
|
|
633
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "additional_configuration" JSONB`));
|
|
634
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "incident_id" UUID`));
|
|
635
|
+
await db.execute(sql.raw(`
|
|
636
|
+
DO $$
|
|
637
|
+
BEGIN
|
|
638
|
+
IF NOT EXISTS (
|
|
639
|
+
SELECT 1 FROM information_schema.columns
|
|
640
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_alerts' AND column_name = 'down_time'
|
|
641
|
+
) THEN
|
|
642
|
+
ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN "down_time" TIMESTAMPTZ;
|
|
643
|
+
END IF;
|
|
644
|
+
|
|
645
|
+
IF EXISTS (
|
|
646
|
+
SELECT 1 FROM information_schema.columns
|
|
647
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_alerts' AND column_name = 'alert_time'
|
|
648
|
+
) THEN
|
|
649
|
+
UPDATE "meyiconnect"."insight_alerts"
|
|
650
|
+
SET "down_time" = COALESCE("down_time", "alert_time", NOW())
|
|
651
|
+
WHERE "down_time" IS NULL;
|
|
652
|
+
ELSE
|
|
653
|
+
UPDATE "meyiconnect"."insight_alerts"
|
|
654
|
+
SET "down_time" = COALESCE("down_time", NOW())
|
|
655
|
+
WHERE "down_time" IS NULL;
|
|
656
|
+
END IF;
|
|
657
|
+
|
|
658
|
+
ALTER TABLE "meyiconnect"."insight_alerts" ALTER COLUMN "down_time" SET NOT NULL;
|
|
659
|
+
ALTER TABLE "meyiconnect"."insight_alerts" ALTER COLUMN "down_time" SET DEFAULT NOW();
|
|
660
|
+
END $$;
|
|
661
|
+
`));
|
|
662
|
+
await db.execute(sql.raw(`
|
|
663
|
+
DO $$
|
|
664
|
+
BEGIN
|
|
665
|
+
IF EXISTS (
|
|
666
|
+
SELECT 1 FROM information_schema.columns
|
|
667
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_alerts' AND column_name = 'promoted_incident_id'
|
|
668
|
+
) THEN
|
|
669
|
+
IF NOT EXISTS (
|
|
670
|
+
SELECT 1 FROM information_schema.columns
|
|
671
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_alerts' AND column_name = 'converted_incident_id'
|
|
672
|
+
) THEN
|
|
673
|
+
ALTER TABLE "meyiconnect"."insight_alerts" RENAME COLUMN "promoted_incident_id" TO "converted_incident_id";
|
|
674
|
+
ELSE
|
|
675
|
+
ALTER TABLE "meyiconnect"."insight_alerts" DROP COLUMN "promoted_incident_id";
|
|
676
|
+
END IF;
|
|
677
|
+
END IF;
|
|
678
|
+
END $$;
|
|
679
|
+
`));
|
|
680
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "converted_incident_id" UUID`));
|
|
681
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "assignee_id" UUID`));
|
|
682
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "dup_count" INT NOT NULL DEFAULT 0`));
|
|
683
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "last_dup_at" TIMESTAMPTZ`));
|
|
684
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "account_id" TEXT`));
|
|
685
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "account_name" TEXT`));
|
|
686
|
+
await db.execute(sql.raw(`
|
|
687
|
+
UPDATE "meyiconnect"."insight_alerts" a
|
|
688
|
+
SET "account_name" = c."account_name"
|
|
689
|
+
FROM "meyiconnect"."connectors" c
|
|
690
|
+
WHERE a."account_name" IS NULL
|
|
691
|
+
AND a."account_id" IS NOT NULL
|
|
692
|
+
AND a."account_id" = c."account_id";
|
|
693
|
+
`));
|
|
694
|
+
await db.execute(sql.raw(`
|
|
695
|
+
UPDATE "meyiconnect"."insight_alerts"
|
|
696
|
+
SET "account_id" = COALESCE(
|
|
697
|
+
"additional_configuration"->>'accountId',
|
|
698
|
+
"raw_payload"->>'account',
|
|
699
|
+
"raw_payload"->>'accountId',
|
|
700
|
+
"raw_payload"->>'AWSAccountId',
|
|
701
|
+
"raw_payload"->'rawEvent'->>'account',
|
|
702
|
+
"raw_payload"->'detail'->>'account',
|
|
703
|
+
"raw_payload"->'detail'->>'recipientAccountId',
|
|
704
|
+
substring("resource_id" FROM 'arn:aws[a-z0-9-]*:cloudwatch:[^:]+:([0-9]{12}):alarm:')
|
|
705
|
+
)
|
|
706
|
+
WHERE "account_id" IS NULL
|
|
707
|
+
AND (
|
|
708
|
+
"additional_configuration"->>'accountId' IS NOT NULL
|
|
709
|
+
OR "raw_payload"->>'account' IS NOT NULL
|
|
710
|
+
OR "raw_payload"->>'accountId' IS NOT NULL
|
|
711
|
+
OR "raw_payload"->>'AWSAccountId' IS NOT NULL
|
|
712
|
+
OR "raw_payload"->'rawEvent'->>'account' IS NOT NULL
|
|
713
|
+
OR "raw_payload"->'detail'->>'account' IS NOT NULL
|
|
714
|
+
OR "raw_payload"->'detail'->>'recipientAccountId' IS NOT NULL
|
|
715
|
+
OR "resource_id" ~ '^arn:aws[a-z0-9-]*:cloudwatch:[^:]+:[0-9]{12}:alarm:'
|
|
716
|
+
)
|
|
717
|
+
`));
|
|
718
|
+
await db.execute(sql.raw(`
|
|
719
|
+
UPDATE "meyiconnect"."insight_alerts"
|
|
720
|
+
SET "additional_configuration" = jsonb_set(
|
|
721
|
+
COALESCE("additional_configuration", '{}'::jsonb),
|
|
722
|
+
'{tags}',
|
|
723
|
+
COALESCE("raw_payload"->'tags', "raw_payload"->'Tags', "raw_payload"->'detail'->'tags')
|
|
724
|
+
)
|
|
725
|
+
WHERE ("additional_configuration" IS NULL OR "additional_configuration"->'tags' IS NULL)
|
|
726
|
+
AND (
|
|
727
|
+
"raw_payload"->'tags' IS NOT NULL
|
|
728
|
+
OR "raw_payload"->'Tags' IS NOT NULL
|
|
729
|
+
OR "raw_payload"->'detail'->'tags' IS NOT NULL
|
|
730
|
+
)
|
|
731
|
+
`));
|
|
732
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_alerts_status_idx ON "meyiconnect"."insight_alerts" ("status")`));
|
|
733
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_alerts_source_idx ON "meyiconnect"."insight_alerts" ("source_id")`));
|
|
734
|
+
// insight_settings
|
|
735
|
+
await db.execute(sql.raw(`
|
|
736
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_settings" (
|
|
737
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
738
|
+
|
|
739
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
740
|
+
)
|
|
741
|
+
`));
|
|
742
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_settings" ADD COLUMN IF NOT EXISTS "aws_bedrock_access_key_id" TEXT`));
|
|
743
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_settings" ADD COLUMN IF NOT EXISTS "aws_bedrock_secret_access_key" TEXT`));
|
|
744
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_settings" ADD COLUMN IF NOT EXISTS "aws_bedrock_region" TEXT`));
|
|
745
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_settings" ADD COLUMN IF NOT EXISTS "tenant_id" TEXT`));
|
|
746
|
+
await db.execute(sql.raw(`UPDATE "meyiconnect"."insight_settings" SET "tenant_id" = '${defaultTenantSql}' WHERE "tenant_id" IS NULL OR "tenant_id" = ''`));
|
|
747
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_settings_tenant_id_idx ON "meyiconnect"."insight_settings" ("tenant_id")`));
|
|
748
|
+
// notification_providers
|
|
749
|
+
await db.execute(sql.raw(`
|
|
750
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."notification_providers" (
|
|
751
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
752
|
+
"tenant_id" TEXT,
|
|
753
|
+
"provider_name" VARCHAR(50) NOT NULL,
|
|
754
|
+
"display_name" VARCHAR(100) NOT NULL,
|
|
755
|
+
"is_enabled" BOOLEAN NOT NULL DEFAULT false,
|
|
756
|
+
"config" JSONB,
|
|
757
|
+
"description" TEXT,
|
|
758
|
+
"icon" TEXT,
|
|
759
|
+
"created_at" TIMESTAMP DEFAULT NOW(),
|
|
760
|
+
"updated_at" TIMESTAMP DEFAULT NOW()
|
|
761
|
+
)
|
|
762
|
+
`));
|
|
763
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."notification_providers" ADD COLUMN IF NOT EXISTS "tenant_id" TEXT`));
|
|
764
|
+
await db.execute(sql.raw(`UPDATE "meyiconnect"."notification_providers" SET "tenant_id" = '${defaultTenantSql}' WHERE "tenant_id" IS NULL OR "tenant_id" = ''`));
|
|
765
|
+
await db.execute(sql.raw(`DROP INDEX IF EXISTS "meyiconnect"."notification_providers_provider_name_unique"`)).catch(() => { });
|
|
766
|
+
await db.execute(sql.raw(`DROP INDEX IF EXISTS notification_providers_provider_name_unique`)).catch(() => { });
|
|
767
|
+
await db.execute(sql.raw(`CREATE UNIQUE INDEX IF NOT EXISTS notification_providers_tenant_name_unique ON "meyiconnect"."notification_providers" ("tenant_id", "provider_name")`));
|
|
768
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS notification_providers_tenant_id_idx ON "meyiconnect"."notification_providers" ("tenant_id")`));
|
|
769
|
+
// incident_events — timestamped audit/timeline log (status changes, assigns, analysis, comments)
|
|
770
|
+
await db.execute(sql.raw(`
|
|
771
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."incident_events" (
|
|
772
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
773
|
+
"incident_id" UUID NOT NULL REFERENCES "meyiconnect"."insight_incidents"("id") ON DELETE CASCADE,
|
|
774
|
+
"type" TEXT NOT NULL,
|
|
775
|
+
"actor" TEXT,
|
|
776
|
+
"message" TEXT,
|
|
777
|
+
"before_value" TEXT,
|
|
778
|
+
"after_value" TEXT,
|
|
779
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
780
|
+
)
|
|
781
|
+
`));
|
|
782
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS incident_events_incident_id_idx ON "meyiconnect"."incident_events" ("incident_id")`));
|
|
783
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS incident_events_created_at_idx ON "meyiconnect"."incident_events" ("created_at")`));
|
|
784
|
+
// incident_logs
|
|
785
|
+
await db.execute(sql.raw(`
|
|
786
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."incident_logs" (
|
|
787
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
788
|
+
"incident_id" UUID NOT NULL REFERENCES "meyiconnect"."insight_incidents"("id") ON DELETE CASCADE,
|
|
789
|
+
"ec2_details" JSONB,
|
|
790
|
+
"ec2_status_checks" JSONB,
|
|
791
|
+
"cloudwatch_metrics" JSONB,
|
|
792
|
+
"raw_logs" JSONB,
|
|
793
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
794
|
+
)
|
|
795
|
+
`));
|
|
796
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS incident_logs_incident_id_idx ON "meyiconnect"."incident_logs" ("incident_id")`));
|
|
797
|
+
// insight_sops
|
|
798
|
+
await db.execute(sql.raw(`
|
|
799
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_sops" (
|
|
800
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
801
|
+
"sop_id" TEXT NOT NULL,
|
|
802
|
+
"title" TEXT NOT NULL,
|
|
803
|
+
"alert_type" TEXT,
|
|
804
|
+
"service" TEXT,
|
|
805
|
+
"severity" TEXT,
|
|
806
|
+
"status" TEXT NOT NULL DEFAULT 'draft',
|
|
807
|
+
"description" TEXT,
|
|
808
|
+
"steps" TEXT,
|
|
809
|
+
"error_response" TEXT,
|
|
810
|
+
"created_by" TEXT DEFAULT 'Manual',
|
|
811
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
812
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
813
|
+
)
|
|
814
|
+
`));
|
|
815
|
+
await db.execute(sql.raw(`DROP INDEX IF EXISTS "meyiconnect"."insight_sops_sop_id_unique"`)).catch(() => { });
|
|
816
|
+
await db.execute(sql.raw(`DROP INDEX IF EXISTS insight_sops_sop_id_unique`)).catch(() => { });
|
|
817
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_sops_status_idx ON "meyiconnect"."insight_sops" ("status")`));
|
|
818
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_sops_severity_idx ON "meyiconnect"."insight_sops" ("severity")`));
|
|
819
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sops" ADD COLUMN IF NOT EXISTS "prompt" TEXT`));
|
|
820
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sops" ADD COLUMN IF NOT EXISTS "error_response" TEXT`));
|
|
821
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sops" ADD COLUMN IF NOT EXISTS "source_id" UUID`));
|
|
822
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sops" ADD COLUMN IF NOT EXISTS "project_id" UUID`));
|
|
823
|
+
await db.execute(sql.raw(`
|
|
824
|
+
DO $$
|
|
825
|
+
BEGIN
|
|
826
|
+
IF EXISTS (
|
|
827
|
+
SELECT 1 FROM information_schema.columns
|
|
828
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_sops' AND column_name = 'incident_id'
|
|
829
|
+
) THEN
|
|
830
|
+
IF NOT EXISTS (
|
|
831
|
+
SELECT 1 FROM information_schema.columns
|
|
832
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_sops' AND column_name = 'alert_id'
|
|
833
|
+
) THEN
|
|
834
|
+
-- Drop old FK before renaming to ensure it points to the correct table
|
|
835
|
+
ALTER TABLE "meyiconnect"."insight_sops" DROP CONSTRAINT IF EXISTS insight_sops_incident_id_fkey;
|
|
836
|
+
ALTER TABLE "meyiconnect"."insight_sops" RENAME COLUMN "incident_id" TO "alert_id";
|
|
837
|
+
ELSE
|
|
838
|
+
ALTER TABLE "meyiconnect"."insight_sops" DROP COLUMN "incident_id";
|
|
839
|
+
END IF;
|
|
840
|
+
END IF;
|
|
841
|
+
END $$;
|
|
842
|
+
`));
|
|
843
|
+
// Drop constraint anyway in case we renamed it but left the constraint intact previously
|
|
844
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sops" DROP CONSTRAINT IF EXISTS insight_sops_incident_id_fkey;`));
|
|
845
|
+
// Add column if it doesn't exist
|
|
846
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sops" ADD COLUMN IF NOT EXISTS "alert_id" UUID`));
|
|
847
|
+
// Explicitly add the new foreign key constraint if it doesn't exist
|
|
848
|
+
await db.execute(sql.raw(`
|
|
849
|
+
DO $$
|
|
850
|
+
BEGIN
|
|
851
|
+
IF NOT EXISTS (
|
|
852
|
+
SELECT 1 FROM information_schema.table_constraints
|
|
853
|
+
WHERE constraint_schema = 'meyiconnect' AND constraint_name = 'insight_sops_alert_id_fkey'
|
|
854
|
+
) THEN
|
|
855
|
+
-- Clear invalid alert_ids (which are actually old incident_ids) before adding the constraint
|
|
856
|
+
UPDATE "meyiconnect"."insight_sops"
|
|
857
|
+
SET alert_id = NULL
|
|
858
|
+
WHERE alert_id IS NOT NULL AND alert_id NOT IN (SELECT id FROM "meyiconnect"."insight_alerts");
|
|
859
|
+
|
|
860
|
+
ALTER TABLE "meyiconnect"."insight_sops" ADD CONSTRAINT insight_sops_alert_id_fkey FOREIGN KEY ("alert_id") REFERENCES "meyiconnect"."insight_alerts"("id") ON DELETE SET NULL;
|
|
861
|
+
END IF;
|
|
862
|
+
END $$;
|
|
863
|
+
`));
|
|
864
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sops" ADD COLUMN IF NOT EXISTS "alert_name" TEXT`));
|
|
865
|
+
await db.execute(sql.raw(`DROP INDEX IF EXISTS "meyiconnect"."insight_sops_alert_name_unique"`)).catch(() => { });
|
|
866
|
+
await db.execute(sql.raw(`DROP INDEX IF EXISTS insight_sops_alert_name_unique`)).catch(() => { });
|
|
867
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sops" ADD COLUMN IF NOT EXISTS "source" TEXT`));
|
|
868
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sops" ADD COLUMN IF NOT EXISTS "project" TEXT`));
|
|
869
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sops" ADD COLUMN IF NOT EXISTS "ai_model_used" TEXT`));
|
|
870
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_sops" ADD COLUMN IF NOT EXISTS "tenant_id" TEXT`));
|
|
871
|
+
await db.execute(sql.raw(`UPDATE "meyiconnect"."insight_sops" SET "tenant_id" = '${defaultTenantSql}' WHERE "tenant_id" IS NULL OR "tenant_id" = ''`));
|
|
872
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_sops_tenant_id_idx ON "meyiconnect"."insight_sops" ("tenant_id")`));
|
|
873
|
+
await db.execute(sql.raw(`CREATE UNIQUE INDEX IF NOT EXISTS insight_sops_tenant_sop_id_unique ON "meyiconnect"."insight_sops" ("tenant_id", "sop_id")`));
|
|
874
|
+
// incident_evidence
|
|
875
|
+
await db.execute(sql.raw(`
|
|
876
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."incident_evidence" (
|
|
877
|
+
"incident_id" UUID PRIMARY KEY REFERENCES "meyiconnect"."insight_incidents"("id") ON DELETE CASCADE,
|
|
878
|
+
"evidence_text" JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
879
|
+
"investigation_findings" JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
880
|
+
"rca_signals" JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
881
|
+
"tool_calls_made" JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
882
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
883
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
884
|
+
)
|
|
885
|
+
`));
|
|
886
|
+
// insight_workflows
|
|
887
|
+
await db.execute(sql.raw(`
|
|
888
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_workflows" (
|
|
889
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
890
|
+
"name" TEXT NOT NULL,
|
|
891
|
+
"description" TEXT,
|
|
892
|
+
"is_active" BOOLEAN NOT NULL DEFAULT true,
|
|
893
|
+
"priority" INTEGER NOT NULL DEFAULT 0,
|
|
894
|
+
"conditions" JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
895
|
+
"actions" JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
896
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
897
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
898
|
+
)
|
|
899
|
+
`));
|
|
900
|
+
await db.execute(sql.raw(`
|
|
901
|
+
ALTER TABLE "meyiconnect"."insight_workflows"
|
|
902
|
+
ADD COLUMN IF NOT EXISTS "yaml_definition" TEXT NOT NULL DEFAULT ''
|
|
903
|
+
`));
|
|
904
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_workflows" ADD COLUMN IF NOT EXISTS "tenant_id" TEXT`));
|
|
905
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_workflows" ADD COLUMN IF NOT EXISTS "source_id" UUID REFERENCES "meyiconnect"."insight_sources"("id") ON DELETE CASCADE`));
|
|
906
|
+
await db.execute(sql.raw(`UPDATE "meyiconnect"."insight_workflows" SET "tenant_id" = '${defaultTenantSql}' WHERE "tenant_id" IS NULL OR "tenant_id" = ''`));
|
|
907
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_workflows_tenant_id_idx ON "meyiconnect"."insight_workflows" ("tenant_id")`));
|
|
908
|
+
await db.execute(sql.raw(`
|
|
909
|
+
ALTER TABLE "meyiconnect"."insight_workflows"
|
|
910
|
+
DROP COLUMN IF EXISTS "conditions"
|
|
911
|
+
`));
|
|
912
|
+
await db.execute(sql.raw(`
|
|
913
|
+
ALTER TABLE "meyiconnect"."insight_workflows"
|
|
914
|
+
DROP COLUMN IF EXISTS "actions"
|
|
915
|
+
`));
|
|
916
|
+
await db.execute(sql.raw(`
|
|
917
|
+
ALTER TABLE "meyiconnect"."insight_workflows"
|
|
918
|
+
DROP COLUMN IF EXISTS "description"
|
|
919
|
+
`));
|
|
920
|
+
// insight_workflow_executions
|
|
921
|
+
await db.execute(sql.raw(`
|
|
922
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_workflow_executions" (
|
|
923
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
924
|
+
"workflow_id" UUID NOT NULL REFERENCES "meyiconnect"."insight_workflows"("id") ON DELETE CASCADE,
|
|
925
|
+
"alert_id" UUID REFERENCES "meyiconnect"."insight_alerts"("id") ON DELETE SET NULL,
|
|
926
|
+
"status" TEXT NOT NULL DEFAULT 'pending',
|
|
927
|
+
"actions_executed" JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
928
|
+
"error_message" TEXT,
|
|
929
|
+
"triggered_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
930
|
+
"completed_at" TIMESTAMPTZ
|
|
931
|
+
)
|
|
932
|
+
`));
|
|
933
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_workflow_executions_workflow_id_idx ON "meyiconnect"."insight_workflow_executions" ("workflow_id")`));
|
|
934
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_workflow_executions_alert_id_idx ON "meyiconnect"."insight_workflow_executions" ("alert_id")`));
|
|
935
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_workflow_executions_status_idx ON "meyiconnect"."insight_workflow_executions" ("status")`));
|
|
936
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_workflow_executions" ADD COLUMN IF NOT EXISTS "tenant_id" TEXT`));
|
|
937
|
+
await db.execute(sql.raw(`
|
|
938
|
+
UPDATE "meyiconnect"."insight_workflow_executions" e
|
|
939
|
+
SET "tenant_id" = COALESCE(w."tenant_id", '${defaultTenantSql}')
|
|
940
|
+
FROM "meyiconnect"."insight_workflows" w
|
|
941
|
+
WHERE e."workflow_id" = w."id"
|
|
942
|
+
AND (e."tenant_id" IS NULL OR e."tenant_id" = '')
|
|
943
|
+
`));
|
|
944
|
+
await db.execute(sql.raw(`UPDATE "meyiconnect"."insight_workflow_executions" SET "tenant_id" = '${defaultTenantSql}' WHERE "tenant_id" IS NULL OR "tenant_id" = ''`));
|
|
945
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_workflow_executions_tenant_id_idx ON "meyiconnect"."insight_workflow_executions" ("tenant_id")`));
|
|
946
|
+
// ─── insight_alerts pipeline columns (Phase 1) ───────────────────────────────
|
|
947
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "fingerprint" TEXT`));
|
|
948
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "dedup_key" TEXT`));
|
|
949
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "pipeline_status" TEXT DEFAULT 'queued'`));
|
|
950
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "group_id" UUID`));
|
|
951
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alerts" ADD COLUMN IF NOT EXISTS "raw_payload" JSONB`));
|
|
952
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_alerts_pipeline_status_idx ON "meyiconnect"."insight_alerts" ("pipeline_status")`));
|
|
953
|
+
// ─── insight_provider_configs ────────────────────────────────────────────────
|
|
954
|
+
await db.execute(sql.raw(`
|
|
955
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_provider_configs" (
|
|
956
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
957
|
+
"tenant_id" TEXT,
|
|
958
|
+
"llm_provider_name" TEXT NOT NULL,
|
|
959
|
+
"llm_model_name" TEXT,
|
|
960
|
+
"llm_model_id" TEXT,
|
|
961
|
+
"llm_api_key" TEXT,
|
|
962
|
+
"is_active" BOOLEAN NOT NULL DEFAULT true,
|
|
963
|
+
"auth_type" TEXT,
|
|
964
|
+
"aws_region" TEXT,
|
|
965
|
+
"aws_access_key_id" TEXT,
|
|
966
|
+
"aws_secret_access_key" TEXT,
|
|
967
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
968
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
969
|
+
)
|
|
970
|
+
`));
|
|
971
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_provider_configs_tenant_id_idx ON "meyiconnect"."insight_provider_configs" ("tenant_id")`));
|
|
972
|
+
// ─── insight_normalization_configs ───────────────────────────────────────────
|
|
973
|
+
await db.execute(sql.raw(`
|
|
974
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_normalization_configs" (
|
|
975
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
976
|
+
"tenant_id" TEXT,
|
|
977
|
+
"name" TEXT NOT NULL,
|
|
978
|
+
"priority" INTEGER NOT NULL DEFAULT 0,
|
|
979
|
+
"is_active" BOOLEAN NOT NULL DEFAULT true,
|
|
980
|
+
"source_id" UUID REFERENCES "meyiconnect"."insight_sources"("id") ON DELETE CASCADE,
|
|
981
|
+
"source_type" TEXT,
|
|
982
|
+
"field_mapping" TEXT NOT NULL DEFAULT '',
|
|
983
|
+
"yaml_definition" TEXT NOT NULL DEFAULT '',
|
|
984
|
+
"is_system" BOOLEAN NOT NULL DEFAULT false,
|
|
985
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
986
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
987
|
+
)
|
|
988
|
+
`));
|
|
989
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_normalization_configs" ADD COLUMN IF NOT EXISTS "is_system" BOOLEAN NOT NULL DEFAULT false`));
|
|
990
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_normalization_configs_priority_idx ON "meyiconnect"."insight_normalization_configs" ("priority")`));
|
|
991
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_normalization_configs_source_type_idx ON "meyiconnect"."insight_normalization_configs" ("source_type")`));
|
|
992
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_normalization_configs" ADD COLUMN IF NOT EXISTS "yaml_definition" TEXT NOT NULL DEFAULT ''`));
|
|
993
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_normalization_configs" ADD COLUMN IF NOT EXISTS "tenant_id" TEXT`));
|
|
994
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_normalization_configs_tenant_id_idx ON "meyiconnect"."insight_normalization_configs" ("tenant_id")`));
|
|
995
|
+
// ─── insight_dedup_configs ───────────────────────────────────────────────────
|
|
996
|
+
await db.execute(sql.raw(`
|
|
997
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_dedup_configs" (
|
|
998
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
999
|
+
"tenant_id" TEXT,
|
|
1000
|
+
"name" TEXT NOT NULL,
|
|
1001
|
+
"priority" INTEGER NOT NULL DEFAULT 0,
|
|
1002
|
+
"is_active" BOOLEAN NOT NULL DEFAULT true,
|
|
1003
|
+
"source_id" UUID REFERENCES "meyiconnect"."insight_sources"("id") ON DELETE CASCADE,
|
|
1004
|
+
"source_type" TEXT,
|
|
1005
|
+
"window_seconds" INTEGER NOT NULL DEFAULT 300,
|
|
1006
|
+
"key_fields" JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
1007
|
+
"flap_threshold" INTEGER NOT NULL DEFAULT 4,
|
|
1008
|
+
"flap_window_seconds" INTEGER NOT NULL DEFAULT 600,
|
|
1009
|
+
"on_flap" TEXT NOT NULL DEFAULT 'none',
|
|
1010
|
+
"yaml_definition" TEXT NOT NULL DEFAULT '',
|
|
1011
|
+
"is_system" BOOLEAN NOT NULL DEFAULT false,
|
|
1012
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
1013
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
1014
|
+
)
|
|
1015
|
+
`));
|
|
1016
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_dedup_configs" ADD COLUMN IF NOT EXISTS "is_system" BOOLEAN NOT NULL DEFAULT false`));
|
|
1017
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_dedup_configs_priority_idx ON "meyiconnect"."insight_dedup_configs" ("priority")`));
|
|
1018
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_dedup_configs_source_type_idx ON "meyiconnect"."insight_dedup_configs" ("source_type")`));
|
|
1019
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_dedup_configs" ADD COLUMN IF NOT EXISTS "yaml_definition" TEXT NOT NULL DEFAULT ''`));
|
|
1020
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_dedup_configs" ADD COLUMN IF NOT EXISTS "tenant_id" TEXT`));
|
|
1021
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_dedup_configs_tenant_id_idx ON "meyiconnect"."insight_dedup_configs" ("tenant_id")`));
|
|
1022
|
+
// ─── insight_grouping_configs ────────────────────────────────────────────────
|
|
1023
|
+
await db.execute(sql.raw(`
|
|
1024
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_grouping_configs" (
|
|
1025
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
1026
|
+
"tenant_id" TEXT,
|
|
1027
|
+
"name" TEXT NOT NULL,
|
|
1028
|
+
"priority" INTEGER NOT NULL DEFAULT 0,
|
|
1029
|
+
"is_active" BOOLEAN NOT NULL DEFAULT true,
|
|
1030
|
+
"source_id" UUID REFERENCES "meyiconnect"."insight_sources"("id") ON DELETE CASCADE,
|
|
1031
|
+
"source_type" TEXT,
|
|
1032
|
+
"group_by" JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
1033
|
+
"timeout_seconds" INTEGER NOT NULL DEFAULT 600,
|
|
1034
|
+
"max_alarms" INTEGER NOT NULL DEFAULT 50,
|
|
1035
|
+
"incident_title_template" TEXT DEFAULT '{{count}} alerts on {{resourceName}}',
|
|
1036
|
+
"use_ai_generate" BOOLEAN NOT NULL DEFAULT false,
|
|
1037
|
+
"yaml_definition" TEXT NOT NULL DEFAULT '',
|
|
1038
|
+
"is_system" BOOLEAN NOT NULL DEFAULT false,
|
|
1039
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
1040
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
1041
|
+
)
|
|
1042
|
+
`));
|
|
1043
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_grouping_configs" ADD COLUMN IF NOT EXISTS "is_system" BOOLEAN NOT NULL DEFAULT false`));
|
|
1044
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_grouping_configs_priority_idx ON "meyiconnect"."insight_grouping_configs" ("priority")`));
|
|
1045
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_grouping_configs_source_type_idx ON "meyiconnect"."insight_grouping_configs" ("source_type")`));
|
|
1046
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_grouping_configs" ADD COLUMN IF NOT EXISTS "yaml_definition" TEXT NOT NULL DEFAULT ''`));
|
|
1047
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_grouping_configs" ADD COLUMN IF NOT EXISTS "tenant_id" TEXT`));
|
|
1048
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_grouping_configs_tenant_id_idx ON "meyiconnect"."insight_grouping_configs" ("tenant_id")`));
|
|
1049
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_grouping_configs" ADD COLUMN IF NOT EXISTS "use_ai_generate" BOOLEAN NOT NULL DEFAULT false`));
|
|
1050
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_grouping_configs" ADD COLUMN IF NOT EXISTS "topology_tag_mapping" TEXT`));
|
|
1051
|
+
// ─── insight_alarm_groups ────────────────────────────────────────────────────
|
|
1052
|
+
await db.execute(sql.raw(`
|
|
1053
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_alarm_groups" (
|
|
1054
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
1055
|
+
"tenant_id" TEXT,
|
|
1056
|
+
"group_key" TEXT NOT NULL,
|
|
1057
|
+
"config_id" UUID REFERENCES "meyiconnect"."insight_grouping_configs"("id") ON DELETE SET NULL,
|
|
1058
|
+
"status" TEXT NOT NULL DEFAULT 'buffering',
|
|
1059
|
+
"first_alarm_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
1060
|
+
"last_alarm_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
1061
|
+
"incident_id" UUID,
|
|
1062
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
1063
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
1064
|
+
)
|
|
1065
|
+
`));
|
|
1066
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_alarm_groups_flush_idx ON "meyiconnect"."insight_alarm_groups" ("status", "last_alarm_at")`));
|
|
1067
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_alarm_groups_group_key_idx ON "meyiconnect"."insight_alarm_groups" ("group_key")`));
|
|
1068
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_alarm_groups" ADD COLUMN IF NOT EXISTS "tenant_id" TEXT`));
|
|
1069
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_alarm_groups_tenant_id_idx ON "meyiconnect"."insight_alarm_groups" ("tenant_id")`));
|
|
1070
|
+
// ─── insight_alarm_group_members (P1 junction table) ─────────────────────────
|
|
1071
|
+
await db.execute(sql.raw(`
|
|
1072
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_alarm_group_members" (
|
|
1073
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
1074
|
+
"group_id" UUID NOT NULL REFERENCES "meyiconnect"."insight_alarm_groups"("id") ON DELETE CASCADE,
|
|
1075
|
+
"alarm_id" UUID NOT NULL REFERENCES "meyiconnect"."insight_alerts"("id") ON DELETE CASCADE,
|
|
1076
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
1077
|
+
)
|
|
1078
|
+
`));
|
|
1079
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_alarm_group_members_group_id_idx ON "meyiconnect"."insight_alarm_group_members" ("group_id")`));
|
|
1080
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_alarm_group_members_alarm_id_idx ON "meyiconnect"."insight_alarm_group_members" ("alarm_id")`));
|
|
1081
|
+
await db.execute(sql.raw(`CREATE UNIQUE INDEX IF NOT EXISTS insight_alarm_group_members_unique_idx ON "meyiconnect"."insight_alarm_group_members" ("group_id", "alarm_id")`));
|
|
1082
|
+
// ─── insight_pipeline_events ─────────────────────────────────────────────────
|
|
1083
|
+
await db.execute(sql.raw(`
|
|
1084
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_pipeline_events" (
|
|
1085
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
1086
|
+
"tenant_id" TEXT,
|
|
1087
|
+
"alarm_id" UUID REFERENCES "meyiconnect"."insight_alerts"("id") ON DELETE CASCADE,
|
|
1088
|
+
"stage" TEXT NOT NULL,
|
|
1089
|
+
"status" TEXT NOT NULL,
|
|
1090
|
+
"matched_config_id" UUID,
|
|
1091
|
+
"meta" JSONB,
|
|
1092
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
1093
|
+
)
|
|
1094
|
+
`));
|
|
1095
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_pipeline_events_alarm_id_idx ON "meyiconnect"."insight_pipeline_events" ("alarm_id")`));
|
|
1096
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_pipeline_events_stage_idx ON "meyiconnect"."insight_pipeline_events" ("stage")`));
|
|
1097
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_pipeline_events_created_at_idx ON "meyiconnect"."insight_pipeline_events" ("created_at")`));
|
|
1098
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_pipeline_events" ADD COLUMN IF NOT EXISTS "tenant_id" TEXT`));
|
|
1099
|
+
await db.execute(sql.raw(`CREATE INDEX IF NOT EXISTS insight_pipeline_events_tenant_id_idx ON "meyiconnect"."insight_pipeline_events" ("tenant_id")`));
|
|
1100
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "description" TEXT`));
|
|
1101
|
+
await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_grouping_configs" ADD COLUMN IF NOT EXISTS "user_prompt" TEXT`));
|
|
1102
|
+
// ─── Seed Pipeline Defaults ──────────────────────────────────────────────────
|
|
1103
|
+
try {
|
|
1104
|
+
const { PipelineDefaults } = await import("../pipeline/defaults/pipelineDefaults.js");
|
|
1105
|
+
for (const [sourceType, configs] of Object.entries(PipelineDefaults)) {
|
|
1106
|
+
if (configs.normalization) {
|
|
1107
|
+
const parsed = yaml.load(configs.normalization.yamlDefinition);
|
|
1108
|
+
const name = parsed.name || `${sourceType} Default Normalization`;
|
|
1109
|
+
await db.execute(sql.raw(`
|
|
1110
|
+
UPDATE "meyiconnect"."insight_normalization_configs"
|
|
1111
|
+
SET "field_mapping" = $token$${configs.normalization.fieldMapping}$token$
|
|
1112
|
+
WHERE "source_type" = '${sourceType}' AND "is_system" = true
|
|
1113
|
+
`));
|
|
1114
|
+
await db.execute(sql.raw(`
|
|
1115
|
+
INSERT INTO "meyiconnect"."insight_normalization_configs"
|
|
1116
|
+
("name", "priority", "is_active", "source_type", "field_mapping", "yaml_definition", "is_system")
|
|
1117
|
+
SELECT '${name}', 10, true, '${sourceType}', $token$${configs.normalization.fieldMapping}$token$, $token$${configs.normalization.yamlDefinition}$token$, true
|
|
1118
|
+
WHERE NOT EXISTS (
|
|
1119
|
+
SELECT 1 FROM "meyiconnect"."insight_normalization_configs"
|
|
1120
|
+
WHERE "source_type" = '${sourceType}' AND "is_system" = true
|
|
1121
|
+
)
|
|
1122
|
+
`));
|
|
1123
|
+
}
|
|
1124
|
+
if (configs.dedup) {
|
|
1125
|
+
const parsed = yaml.load(configs.dedup.yamlDefinition);
|
|
1126
|
+
const name = parsed.name || `${sourceType} Default Deduplication`;
|
|
1127
|
+
await db.execute(sql.raw(`
|
|
1128
|
+
INSERT INTO "meyiconnect"."insight_dedup_configs"
|
|
1129
|
+
("name", "priority", "is_active", "source_type", "yaml_definition", "is_system")
|
|
1130
|
+
SELECT '${name}', 10, true, '${sourceType}', $token$${configs.dedup.yamlDefinition}$token$, true
|
|
1131
|
+
WHERE NOT EXISTS (
|
|
1132
|
+
SELECT 1 FROM "meyiconnect"."insight_dedup_configs"
|
|
1133
|
+
WHERE "source_type" = '${sourceType}' AND "is_system" = true
|
|
1134
|
+
)
|
|
1135
|
+
`));
|
|
1136
|
+
}
|
|
1137
|
+
if (configs.grouping) {
|
|
1138
|
+
const parsed = yaml.load(configs.grouping.yamlDefinition);
|
|
1139
|
+
const name = parsed.name || `${sourceType} Default Grouping`;
|
|
1140
|
+
await db.execute(sql.raw(`
|
|
1141
|
+
INSERT INTO "meyiconnect"."insight_grouping_configs"
|
|
1142
|
+
("name", "priority", "is_active", "source_type", "yaml_definition", "is_system")
|
|
1143
|
+
SELECT '${name}', 10, true, '${sourceType}', $token$${configs.grouping.yamlDefinition}$token$, true
|
|
1144
|
+
WHERE NOT EXISTS (
|
|
1145
|
+
SELECT 1 FROM "meyiconnect"."insight_grouping_configs"
|
|
1146
|
+
WHERE "source_type" = '${sourceType}' AND "is_system" = true
|
|
1147
|
+
)
|
|
1148
|
+
`));
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
catch (err) {
|
|
1153
|
+
console.error("Failed to seed pipeline defaults:", err.message);
|
|
1154
|
+
}
|
|
1155
|
+
// ─── insight_connectors ────────────────────────────────────────────────────
|
|
1156
|
+
// Denormalized connector table written by marketplace-service during
|
|
1157
|
+
// onboarding. insight-server reads from this table for the Connectors page.
|
|
1158
|
+
await db.execute(sql.raw(`
|
|
1159
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_connectors" (
|
|
1160
|
+
"id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
1161
|
+
"tenant_id" TEXT NOT NULL,
|
|
1162
|
+
"account_id" TEXT NOT NULL,
|
|
1163
|
+
"account_name" TEXT NOT NULL,
|
|
1164
|
+
"email" TEXT,
|
|
1165
|
+
"access_status" TEXT NOT NULL DEFAULT 'Active',
|
|
1166
|
+
"connection_status" TEXT NOT NULL DEFAULT 'PENDING',
|
|
1167
|
+
"connection_id" TEXT NOT NULL,
|
|
1168
|
+
"management_account_id" TEXT,
|
|
1169
|
+
"external_id" TEXT NOT NULL,
|
|
1170
|
+
"role_name" TEXT NOT NULL,
|
|
1171
|
+
"role_arn" TEXT NOT NULL,
|
|
1172
|
+
"selected" BOOLEAN NOT NULL DEFAULT false,
|
|
1173
|
+
"joined_method" TEXT,
|
|
1174
|
+
"connected_at" TIMESTAMPTZ,
|
|
1175
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
1176
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
1177
|
+
)
|
|
1178
|
+
`));
|
|
1179
|
+
await db.execute(sql.raw(`
|
|
1180
|
+
CREATE UNIQUE INDEX IF NOT EXISTS insight_connectors_tenant_account_unique
|
|
1181
|
+
ON "meyiconnect"."insight_connectors" ("tenant_id", "account_id")
|
|
1182
|
+
`));
|
|
1183
|
+
await db.execute(sql.raw(`
|
|
1184
|
+
CREATE INDEX IF NOT EXISTS insight_connectors_tenant_idx
|
|
1185
|
+
ON "meyiconnect"."insight_connectors" ("tenant_id")
|
|
1186
|
+
`));
|
|
1187
|
+
await db.execute(sql.raw(`
|
|
1188
|
+
CREATE INDEX IF NOT EXISTS insight_connectors_connection_idx
|
|
1189
|
+
ON "meyiconnect"."insight_connectors" ("connection_id")
|
|
1190
|
+
`));
|
|
1191
|
+
await db.execute(sql.raw(`
|
|
1192
|
+
CREATE INDEX IF NOT EXISTS insight_connectors_access_status_idx
|
|
1193
|
+
ON "meyiconnect"."insight_connectors" ("access_status")
|
|
1194
|
+
`));
|
|
1195
|
+
// ─── insight_job_queue ────────────────────────────────────────────────────
|
|
1196
|
+
await db.execute(sql.raw(`
|
|
1197
|
+
CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_job_queue" (
|
|
1198
|
+
"id" SERIAL PRIMARY KEY,
|
|
1199
|
+
"job_type" TEXT NOT NULL,
|
|
1200
|
+
"payload" JSONB NOT NULL,
|
|
1201
|
+
"status" TEXT NOT NULL DEFAULT 'pending',
|
|
1202
|
+
"attempts" INTEGER NOT NULL DEFAULT 0,
|
|
1203
|
+
"max_attempts" INTEGER NOT NULL DEFAULT 3,
|
|
1204
|
+
"available_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
1205
|
+
"leased_by" TEXT,
|
|
1206
|
+
"leased_at" TIMESTAMPTZ,
|
|
1207
|
+
"last_error" TEXT,
|
|
1208
|
+
"created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
1209
|
+
"updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
1210
|
+
)
|
|
1211
|
+
`));
|
|
1212
|
+
await db.execute(sql.raw(`
|
|
1213
|
+
CREATE INDEX IF NOT EXISTS insight_job_queue_fetch_idx
|
|
1214
|
+
ON "meyiconnect"."insight_job_queue" ("job_type", "status", "available_at")
|
|
1215
|
+
`));
|
|
1216
|
+
// ─── generic tags migration & project_tag removal ─────────────────────────
|
|
1217
|
+
await db.execute(sql.raw(`
|
|
1218
|
+
ALTER TABLE "meyiconnect"."insight_alerts"
|
|
1219
|
+
ADD COLUMN IF NOT EXISTS "tags" JSONB NOT NULL DEFAULT '{}'::jsonb;
|
|
1220
|
+
`));
|
|
1221
|
+
await db.execute(sql.raw(`
|
|
1222
|
+
ALTER TABLE "meyiconnect"."insight_incidents"
|
|
1223
|
+
ADD COLUMN IF NOT EXISTS "tags" JSONB NOT NULL DEFAULT '{}'::jsonb;
|
|
1224
|
+
`));
|
|
1225
|
+
await db.execute(sql.raw(`
|
|
1226
|
+
DO $$
|
|
1227
|
+
BEGIN
|
|
1228
|
+
IF EXISTS (
|
|
1229
|
+
SELECT 1 FROM information_schema.columns
|
|
1230
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_alerts' AND column_name = 'project_tag'
|
|
1231
|
+
) THEN
|
|
1232
|
+
UPDATE "meyiconnect"."insight_alerts"
|
|
1233
|
+
SET "tags" = COALESCE("tags", '{}'::jsonb)
|
|
1234
|
+
|| CASE WHEN "additional_configuration"->'tags' IS NOT NULL THEN ("additional_configuration"->'tags') ELSE '{}'::jsonb END
|
|
1235
|
+
|| CASE WHEN "project_tag" IS NOT NULL AND "project_tag" != '' THEN jsonb_build_object('project', "project_tag") ELSE '{}'::jsonb END;
|
|
1236
|
+
|
|
1237
|
+
DROP INDEX IF EXISTS "meyiconnect"."insight_alerts_project_tag_idx";
|
|
1238
|
+
ALTER TABLE "meyiconnect"."insight_alerts" DROP COLUMN "project_tag";
|
|
1239
|
+
END IF;
|
|
1240
|
+
|
|
1241
|
+
IF EXISTS (
|
|
1242
|
+
SELECT 1 FROM information_schema.columns
|
|
1243
|
+
WHERE table_schema = 'meyiconnect' AND table_name = 'insight_incidents' AND column_name = 'project_tag'
|
|
1244
|
+
) THEN
|
|
1245
|
+
UPDATE "meyiconnect"."insight_incidents"
|
|
1246
|
+
SET "tags" = COALESCE("tags", '{}'::jsonb)
|
|
1247
|
+
|| CASE WHEN "project_tag" IS NOT NULL AND "project_tag" != '' THEN jsonb_build_object('project', "project_tag") ELSE '{}'::jsonb END;
|
|
1248
|
+
|
|
1249
|
+
ALTER TABLE "meyiconnect"."insight_incidents" DROP COLUMN "project_tag";
|
|
1250
|
+
END IF;
|
|
1251
|
+
END $$;
|
|
1252
|
+
`));
|
|
1253
|
+
await db.execute(sql.raw(`
|
|
1254
|
+
CREATE INDEX IF NOT EXISTS insight_alerts_tags_idx
|
|
1255
|
+
ON "meyiconnect"."insight_alerts" USING GIN ("tags");
|
|
1256
|
+
`));
|
|
1257
|
+
await db.execute(sql.raw(`
|
|
1258
|
+
CREATE INDEX IF NOT EXISTS insight_incidents_tags_idx
|
|
1259
|
+
ON "meyiconnect"."insight_incidents" USING GIN ("tags");
|
|
1260
|
+
`));
|
|
1261
|
+
}
|
|
1262
|
+
//# sourceMappingURL=run.js.map
|