@oneuptime/common 12.0.20 → 12.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/Models/AnalyticsModels/ChangeEvent.ts +331 -0
  2. package/Models/AnalyticsModels/Index.ts +2 -0
  3. package/Server/EnvironmentConfig.ts +1 -8
  4. package/Server/Infrastructure/Postgres/SchemaMigrations/1789000000000-AddUserSlackAndMicrosoftTeams.ts +42 -0
  5. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +0 -2
  6. package/Server/Services/ChangeEventService.ts +11 -0
  7. package/Server/Services/EnterpriseLicenseService.ts +3 -3
  8. package/Server/Services/Index.ts +2 -0
  9. package/Server/Utils/Attribution.ts +11 -11
  10. package/Server/Utils/Marketing/MarketingEventWebhook.ts +4 -5
  11. package/Server/Utils/Telemetry/ChangeEventRow.ts +228 -0
  12. package/Server/Views/Partials/AnalyticsConsent.ejs +3 -95
  13. package/Tests/App/Dashboard/DashboardChartWidgetZoom.test.tsx +64 -0
  14. package/Tests/App/Dashboard/EventOverlayHook.test.tsx +249 -0
  15. package/Tests/App/Dashboard/InvestigationArtifacts.test.tsx +315 -0
  16. package/Tests/App/Dashboard/InvestigationDrawer.test.tsx +258 -0
  17. package/Tests/App/Dashboard/MetricChartsCompare.test.tsx +171 -0
  18. package/Tests/App/Dashboard/MetricViewCompare.test.tsx +233 -0
  19. package/Tests/Server/Infrastructure/Postgres/AddUserSlackAndMicrosoftTeamsMigration.test.ts +236 -0
  20. package/Tests/Server/Utils/AI/SRE/Insights/Detectors/ExceptionIdentity.test.ts +224 -0
  21. package/Tests/Server/Utils/Attribution.test.ts +4 -5
  22. package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +2 -2
  23. package/Tests/Server/Utils/Monitor/MonitorCriteriaExpectationBuilder.test.ts +300 -0
  24. package/Tests/UI/Components/Charts/ChartGhostSeries.test.tsx +103 -0
  25. package/Tests/UI/Components/Charts/TooltipEntries.test.ts +44 -8
  26. package/Tests/Utils/Telemetry/CrossSignalScope.test.ts +13 -2
  27. package/Types/AnalyticsDatabase/AnalyticsTableName.ts +7 -0
  28. package/Types/Marketing/Attribution.ts +9 -15
  29. package/Types/Marketing/MarketingEvent.ts +10 -46
  30. package/UI/Components/Charts/Area/AreaChart.tsx +15 -0
  31. package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +16 -1
  32. package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +189 -93
  33. package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +6 -1
  34. package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +213 -114
  35. package/UI/Components/Charts/ChartLibrary/Utils/TooltipEntries.ts +42 -27
  36. package/UI/Components/Charts/Line/LineChart.tsx +15 -0
  37. package/Utils/Metrics/MetricExplorerUrl.ts +119 -5
  38. package/Utils/Telemetry/CrossSignalScope.ts +19 -10
  39. package/build/dist/Models/AnalyticsModels/ChangeEvent.js +298 -0
  40. package/build/dist/Models/AnalyticsModels/ChangeEvent.js.map +1 -0
  41. package/build/dist/Models/AnalyticsModels/Index.js +2 -0
  42. package/build/dist/Models/AnalyticsModels/Index.js.map +1 -1
  43. package/build/dist/Server/EnvironmentConfig.js +1 -7
  44. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  45. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789000000000-AddUserSlackAndMicrosoftTeams.js +39 -0
  46. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789000000000-AddUserSlackAndMicrosoftTeams.js.map +1 -1
  47. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +0 -2
  48. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  49. package/build/dist/Server/Services/ChangeEventService.js +9 -0
  50. package/build/dist/Server/Services/ChangeEventService.js.map +1 -0
  51. package/build/dist/Server/Services/EnterpriseLicenseService.js +3 -3
  52. package/build/dist/Server/Services/Index.js +2 -0
  53. package/build/dist/Server/Services/Index.js.map +1 -1
  54. package/build/dist/Server/Utils/Attribution.js +6 -6
  55. package/build/dist/Server/Utils/Marketing/MarketingEventWebhook.js +4 -5
  56. package/build/dist/Server/Utils/Marketing/MarketingEventWebhook.js.map +1 -1
  57. package/build/dist/Server/Utils/Telemetry/ChangeEventRow.js +150 -0
  58. package/build/dist/Server/Utils/Telemetry/ChangeEventRow.js.map +1 -0
  59. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js +7 -0
  60. package/build/dist/Types/AnalyticsDatabase/AnalyticsTableName.js.map +1 -1
  61. package/build/dist/Types/Marketing/Attribution.js +9 -15
  62. package/build/dist/Types/Marketing/Attribution.js.map +1 -1
  63. package/build/dist/Types/Marketing/MarketingEvent.js +2 -33
  64. package/build/dist/Types/Marketing/MarketingEvent.js.map +1 -1
  65. package/build/dist/UI/Components/Charts/Area/AreaChart.js +1 -1
  66. package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
  67. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +9 -1
  68. package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
  69. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +92 -38
  70. package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
  71. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +8 -8
  72. package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
  73. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +95 -37
  74. package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
  75. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/TooltipEntries.js +39 -24
  76. package/build/dist/UI/Components/Charts/ChartLibrary/Utils/TooltipEntries.js.map +1 -1
  77. package/build/dist/UI/Components/Charts/Line/LineChart.js +1 -1
  78. package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
  79. package/build/dist/Utils/Metrics/MetricExplorerUrl.js +81 -0
  80. package/build/dist/Utils/Metrics/MetricExplorerUrl.js.map +1 -1
  81. package/build/dist/Utils/Telemetry/CrossSignalScope.js +14 -8
  82. package/build/dist/Utils/Telemetry/CrossSignalScope.js.map +1 -1
  83. package/package.json +1 -1
  84. package/Server/Infrastructure/Postgres/SchemaMigrations/1788900000000-RedactStoredMonitorIngestSecrets.ts +0 -117
  85. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1788900000000-RedactStoredMonitorIngestSecrets.js +0 -106
  86. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1788900000000-RedactStoredMonitorIngestSecrets.js.map +0 -1
@@ -1,117 +0,0 @@
1
- import { MigrationInterface, QueryRunner } from "typeorm";
2
-
3
- /*
4
- * Scrub monitor ingest keys out of payloads that were already persisted.
5
- *
6
- * https://github.com/OneUptime/oneuptime/issues/3360
7
- *
8
- * An Incoming Email monitor's `incomingEmailSecretKey` IS its inbound address:
9
- * `SendGridInboundProvider.generateMonitorEmailAddress` builds
10
- * `monitor-{secretKey}@{inboundDomain}`, and `extractSecretKeyFromEmail` reads
11
- * the key straight back out. Every stored copy of the recipient was therefore a
12
- * stored copy of a live bearer credential — `emailTo`, the `To:` header, and
13
- * the `Received:` / `Delivered-To:` headers added in transit.
14
- *
15
- * `ProcessProbeIngest.processIncomingEmailFromQueue` now masks the key at the
16
- * ingest boundary, so nothing written from here on carries it. That fixes the
17
- * flow and not the stock: rows written before this deploy still hold the key in
18
- * plaintext, in columns a `Permission.Viewer` can select. Narrowing a read ACL
19
- * would not have helped either — the same snapshot is copied onto incidents and
20
- * alerts, which are gated on their own permissions.
21
- *
22
- * The four Postgres sinks, all of them jsonb:
23
- *
24
- * - `Monitor.incomingEmailMonitorRequest` (the reported leak)
25
- * - `Monitor.incomingMonitorRequest` (same shape, `incomingRequestSecretKey`)
26
- * - `Incident.monitorSummary` (via MonitorSummaryCapture)
27
- * - `Alert.monitorSummary` (via MonitorSummaryCapture)
28
- *
29
- * `MonitorLog.logBody` is the fifth sink and is deliberately not touched here:
30
- * it lives in ClickHouse, not Postgres, and every row carries a `retentionDate`
31
- * with a `retentionDate DELETE` TTL, so historical rows age out on their own.
32
- *
33
- * Matching is case-insensitive (`gi`). A uuid renders lowercase in Postgres,
34
- * but the key reaches these payloads through relay headers that preserve
35
- * whatever case the sender used. A uuid is made of hex digits and hyphens, so
36
- * it needs no regex escaping, and the replacement text contains no backslash,
37
- * so it needs none either.
38
- */
39
- export class RedactStoredMonitorIngestSecrets1788900000000
40
- implements MigrationInterface
41
- {
42
- public name: string = "RedactStoredMonitorIngestSecrets1788900000000";
43
-
44
- public async up(queryRunner: QueryRunner): Promise<void> {
45
- /*
46
- * The monitor's own row: the key and the payload quoting it are on the
47
- * same row, so this needs no join.
48
- */
49
- await queryRunner.query(
50
- `UPDATE "Monitor"
51
- SET "incomingEmailMonitorRequest" = regexp_replace(
52
- "incomingEmailMonitorRequest"::text,
53
- "incomingEmailSecretKey"::text,
54
- '[REDACTED]',
55
- 'gi'
56
- )::jsonb
57
- WHERE "incomingEmailSecretKey" IS NOT NULL
58
- AND "incomingEmailMonitorRequest" IS NOT NULL
59
- AND "incomingEmailMonitorRequest"::text ILIKE '%' || "incomingEmailSecretKey"::text || '%'`,
60
- );
61
-
62
- await queryRunner.query(
63
- `UPDATE "Monitor"
64
- SET "incomingMonitorRequest" = regexp_replace(
65
- "incomingMonitorRequest"::text,
66
- "incomingRequestSecretKey"::text,
67
- '[REDACTED]',
68
- 'gi'
69
- )::jsonb
70
- WHERE "incomingRequestSecretKey" IS NOT NULL
71
- AND "incomingMonitorRequest" IS NOT NULL
72
- AND "incomingMonitorRequest"::text ILIKE '%' || "incomingRequestSecretKey"::text || '%'`,
73
- );
74
-
75
- /*
76
- * Incident and Alert keep a copy of the snapshot the monitor was evaluated
77
- * from. The key is not on those rows, so join back to the monitor. The
78
- * `projectId` equality keeps the join from degenerating into a cross
79
- * product; the ILIKE is what actually selects the affected rows, and a
80
- * snapshot describes exactly one monitor, so at most one monitor row can
81
- * match a given summary.
82
- */
83
- for (const table of ["Incident", "Alert"]) {
84
- for (const secretColumn of [
85
- "incomingEmailSecretKey",
86
- "incomingRequestSecretKey",
87
- ]) {
88
- await queryRunner.query(
89
- `UPDATE "${table}" AS t
90
- SET "monitorSummary" = regexp_replace(
91
- t."monitorSummary"::text,
92
- m."${secretColumn}"::text,
93
- '[REDACTED]',
94
- 'gi'
95
- )::jsonb
96
- FROM "Monitor" AS m
97
- WHERE m."${secretColumn}" IS NOT NULL
98
- AND m."projectId" = t."projectId"
99
- AND t."monitorSummary" IS NOT NULL
100
- AND t."monitorSummary"::text ILIKE '%' || m."${secretColumn}"::text || '%'`,
101
- );
102
- }
103
- }
104
- }
105
-
106
- public async down(): Promise<void> {
107
- /*
108
- * Deliberately empty. The whole point of the up migration is that these
109
- * values are gone; the original text is not recoverable from anything else
110
- * in the schema, and recovering it would mean re-publishing the leak.
111
- *
112
- * Nothing depends on the redacted text either: `IncomingEmailCriteria`
113
- * re-evaluates against live mail, and the summary cards render whatever
114
- * string is stored. Rolling the schema back therefore needs no data change.
115
- */
116
- }
117
- }
@@ -1,106 +0,0 @@
1
- /*
2
- * Scrub monitor ingest keys out of payloads that were already persisted.
3
- *
4
- * https://github.com/OneUptime/oneuptime/issues/3360
5
- *
6
- * An Incoming Email monitor's `incomingEmailSecretKey` IS its inbound address:
7
- * `SendGridInboundProvider.generateMonitorEmailAddress` builds
8
- * `monitor-{secretKey}@{inboundDomain}`, and `extractSecretKeyFromEmail` reads
9
- * the key straight back out. Every stored copy of the recipient was therefore a
10
- * stored copy of a live bearer credential — `emailTo`, the `To:` header, and
11
- * the `Received:` / `Delivered-To:` headers added in transit.
12
- *
13
- * `ProcessProbeIngest.processIncomingEmailFromQueue` now masks the key at the
14
- * ingest boundary, so nothing written from here on carries it. That fixes the
15
- * flow and not the stock: rows written before this deploy still hold the key in
16
- * plaintext, in columns a `Permission.Viewer` can select. Narrowing a read ACL
17
- * would not have helped either — the same snapshot is copied onto incidents and
18
- * alerts, which are gated on their own permissions.
19
- *
20
- * The four Postgres sinks, all of them jsonb:
21
- *
22
- * - `Monitor.incomingEmailMonitorRequest` (the reported leak)
23
- * - `Monitor.incomingMonitorRequest` (same shape, `incomingRequestSecretKey`)
24
- * - `Incident.monitorSummary` (via MonitorSummaryCapture)
25
- * - `Alert.monitorSummary` (via MonitorSummaryCapture)
26
- *
27
- * `MonitorLog.logBody` is the fifth sink and is deliberately not touched here:
28
- * it lives in ClickHouse, not Postgres, and every row carries a `retentionDate`
29
- * with a `retentionDate DELETE` TTL, so historical rows age out on their own.
30
- *
31
- * Matching is case-insensitive (`gi`). A uuid renders lowercase in Postgres,
32
- * but the key reaches these payloads through relay headers that preserve
33
- * whatever case the sender used. A uuid is made of hex digits and hyphens, so
34
- * it needs no regex escaping, and the replacement text contains no backslash,
35
- * so it needs none either.
36
- */
37
- export class RedactStoredMonitorIngestSecrets1788900000000 {
38
- constructor() {
39
- this.name = "RedactStoredMonitorIngestSecrets1788900000000";
40
- }
41
- async up(queryRunner) {
42
- /*
43
- * The monitor's own row: the key and the payload quoting it are on the
44
- * same row, so this needs no join.
45
- */
46
- await queryRunner.query(`UPDATE "Monitor"
47
- SET "incomingEmailMonitorRequest" = regexp_replace(
48
- "incomingEmailMonitorRequest"::text,
49
- "incomingEmailSecretKey"::text,
50
- '[REDACTED]',
51
- 'gi'
52
- )::jsonb
53
- WHERE "incomingEmailSecretKey" IS NOT NULL
54
- AND "incomingEmailMonitorRequest" IS NOT NULL
55
- AND "incomingEmailMonitorRequest"::text ILIKE '%' || "incomingEmailSecretKey"::text || '%'`);
56
- await queryRunner.query(`UPDATE "Monitor"
57
- SET "incomingMonitorRequest" = regexp_replace(
58
- "incomingMonitorRequest"::text,
59
- "incomingRequestSecretKey"::text,
60
- '[REDACTED]',
61
- 'gi'
62
- )::jsonb
63
- WHERE "incomingRequestSecretKey" IS NOT NULL
64
- AND "incomingMonitorRequest" IS NOT NULL
65
- AND "incomingMonitorRequest"::text ILIKE '%' || "incomingRequestSecretKey"::text || '%'`);
66
- /*
67
- * Incident and Alert keep a copy of the snapshot the monitor was evaluated
68
- * from. The key is not on those rows, so join back to the monitor. The
69
- * `projectId` equality keeps the join from degenerating into a cross
70
- * product; the ILIKE is what actually selects the affected rows, and a
71
- * snapshot describes exactly one monitor, so at most one monitor row can
72
- * match a given summary.
73
- */
74
- for (const table of ["Incident", "Alert"]) {
75
- for (const secretColumn of [
76
- "incomingEmailSecretKey",
77
- "incomingRequestSecretKey",
78
- ]) {
79
- await queryRunner.query(`UPDATE "${table}" AS t
80
- SET "monitorSummary" = regexp_replace(
81
- t."monitorSummary"::text,
82
- m."${secretColumn}"::text,
83
- '[REDACTED]',
84
- 'gi'
85
- )::jsonb
86
- FROM "Monitor" AS m
87
- WHERE m."${secretColumn}" IS NOT NULL
88
- AND m."projectId" = t."projectId"
89
- AND t."monitorSummary" IS NOT NULL
90
- AND t."monitorSummary"::text ILIKE '%' || m."${secretColumn}"::text || '%'`);
91
- }
92
- }
93
- }
94
- async down() {
95
- /*
96
- * Deliberately empty. The whole point of the up migration is that these
97
- * values are gone; the original text is not recoverable from anything else
98
- * in the schema, and recovering it would mean re-publishing the leak.
99
- *
100
- * Nothing depends on the redacted text either: `IncomingEmailCriteria`
101
- * re-evaluates against live mail, and the summary cards render whatever
102
- * string is stored. Rolling the schema back therefore needs no data change.
103
- */
104
- }
105
- }
106
- //# sourceMappingURL=1788900000000-RedactStoredMonitorIngestSecrets.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"1788900000000-RedactStoredMonitorIngestSecrets.js","sourceRoot":"","sources":["../../../../../../Server/Infrastructure/Postgres/SchemaMigrations/1788900000000-RedactStoredMonitorIngestSecrets.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,OAAO,6CAA6C;IAA1D;QAGS,SAAI,GAAW,+CAA+C,CAAC;IA2ExE,CAAC;IAzEQ,KAAK,CAAC,EAAE,CAAC,WAAwB;QACtC;;;WAGG;QACH,MAAM,WAAW,CAAC,KAAK,CACrB;;;;;;;;;qGAS+F,CAChG,CAAC;QAEF,MAAM,WAAW,CAAC,KAAK,CACrB;;;;;;;;;kGAS4F,CAC7F,CAAC;QAEF;;;;;;;WAOG;QACH,KAAK,MAAM,KAAK,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,CAAC;YAC1C,KAAK,MAAM,YAAY,IAAI;gBACzB,wBAAwB;gBACxB,0BAA0B;aAC3B,EAAE,CAAC;gBACF,MAAM,WAAW,CAAC,KAAK,CACrB,WAAW,KAAK;;;yBAGD,YAAY;;;;;uBAKd,YAAY;;;6DAG0B,YAAY,gBAAgB,CAChF,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,IAAI;QACf;;;;;;;;WAQG;IACL,CAAC;CACF"}