@debugbundle/cli 1.8.1 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.cjs +685 -435
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -39659,17 +39659,17 @@ var require_dns = __commonJS({
|
|
|
39659
39659
|
const timestamp = Date.now();
|
|
39660
39660
|
const records = { records: { 4: null, 6: null } };
|
|
39661
39661
|
let minTTL = this.#maxTTL;
|
|
39662
|
-
for (const
|
|
39663
|
-
|
|
39664
|
-
if (typeof
|
|
39665
|
-
|
|
39666
|
-
minTTL = Math.min(minTTL,
|
|
39662
|
+
for (const record2 of addresses) {
|
|
39663
|
+
record2.timestamp = timestamp;
|
|
39664
|
+
if (typeof record2.ttl === "number") {
|
|
39665
|
+
record2.ttl = Math.min(record2.ttl, this.#maxTTL);
|
|
39666
|
+
minTTL = Math.min(minTTL, record2.ttl);
|
|
39667
39667
|
} else {
|
|
39668
|
-
|
|
39668
|
+
record2.ttl = this.#maxTTL;
|
|
39669
39669
|
}
|
|
39670
|
-
const familyRecords = records.records[
|
|
39671
|
-
familyRecords.ips.push(
|
|
39672
|
-
records.records[
|
|
39670
|
+
const familyRecords = records.records[record2.family] ?? { ips: [] };
|
|
39671
|
+
familyRecords.ips.push(record2);
|
|
39672
|
+
records.records[record2.family] = familyRecords;
|
|
39673
39673
|
}
|
|
39674
39674
|
this.storage.set(origin.hostname, records, { ttl: minTTL });
|
|
39675
39675
|
}
|
|
@@ -55119,15 +55119,15 @@ var require_util7 = __commonJS({
|
|
|
55119
55119
|
exports2.getUniqueHostnamesFromOptions = getUniqueHostnamesFromOptions;
|
|
55120
55120
|
function groupSrvRecords(records) {
|
|
55121
55121
|
const recordsByPriority = {};
|
|
55122
|
-
for (const
|
|
55123
|
-
if (!recordsByPriority.hasOwnProperty(
|
|
55124
|
-
recordsByPriority[
|
|
55125
|
-
totalWeight:
|
|
55126
|
-
records: [
|
|
55122
|
+
for (const record2 of records) {
|
|
55123
|
+
if (!recordsByPriority.hasOwnProperty(record2.priority)) {
|
|
55124
|
+
recordsByPriority[record2.priority] = {
|
|
55125
|
+
totalWeight: record2.weight,
|
|
55126
|
+
records: [record2]
|
|
55127
55127
|
};
|
|
55128
55128
|
} else {
|
|
55129
|
-
recordsByPriority[
|
|
55130
|
-
recordsByPriority[
|
|
55129
|
+
recordsByPriority[record2.priority].totalWeight += record2.weight;
|
|
55130
|
+
recordsByPriority[record2.priority].records.push(record2);
|
|
55131
55131
|
}
|
|
55132
55132
|
}
|
|
55133
55133
|
return recordsByPriority;
|
|
@@ -55140,12 +55140,12 @@ var require_util7 = __commonJS({
|
|
|
55140
55140
|
}
|
|
55141
55141
|
const random = Math.floor(Math.random() * (recordsGroup.totalWeight + recordsGroup.records.length));
|
|
55142
55142
|
let total = 0;
|
|
55143
|
-
for (const [i,
|
|
55144
|
-
total += 1 +
|
|
55143
|
+
for (const [i, record2] of recordsGroup.records.entries()) {
|
|
55144
|
+
total += 1 + record2.weight;
|
|
55145
55145
|
if (total > random) {
|
|
55146
|
-
recordsGroup.totalWeight -=
|
|
55146
|
+
recordsGroup.totalWeight -= record2.weight;
|
|
55147
55147
|
recordsGroup.records.splice(i, 1);
|
|
55148
|
-
return
|
|
55148
|
+
return record2;
|
|
55149
55149
|
}
|
|
55150
55150
|
}
|
|
55151
55151
|
}
|
|
@@ -57067,13 +57067,13 @@ var require_cluster = __commonJS({
|
|
|
57067
57067
|
if (!sortedKeys.length) {
|
|
57068
57068
|
return reject(err2);
|
|
57069
57069
|
}
|
|
57070
|
-
const key = sortedKeys[0], group = groupedRecords[key],
|
|
57070
|
+
const key = sortedKeys[0], group = groupedRecords[key], record2 = (0, util_1.weightSrvRecords)(group);
|
|
57071
57071
|
if (!group.records.length) {
|
|
57072
57072
|
sortedKeys.shift();
|
|
57073
57073
|
}
|
|
57074
|
-
self.dnsLookup(
|
|
57074
|
+
self.dnsLookup(record2.name).then((host) => resolve2({
|
|
57075
57075
|
host,
|
|
57076
|
-
port:
|
|
57076
|
+
port: record2.port
|
|
57077
57077
|
}), tryFirstOne);
|
|
57078
57078
|
}
|
|
57079
57079
|
tryFirstOne();
|
|
@@ -63786,6 +63786,73 @@ function createEventEnvelope(input3) {
|
|
|
63786
63786
|
return EventEnvelopeSchema.parse(candidate);
|
|
63787
63787
|
}
|
|
63788
63788
|
|
|
63789
|
+
// ../../packages/shared-types/src/browser-resource-routes.ts
|
|
63790
|
+
var BrowserResourceRoutesSchema = external_exports.object({
|
|
63791
|
+
items: external_exports.array(external_exports.object({ route: external_exports.string().max(1024), occurrences: external_exports.number().int().positive() })).max(20),
|
|
63792
|
+
recorded_occurrences: external_exports.number().int().nonnegative(),
|
|
63793
|
+
unattributed_occurrences: external_exports.number().int().nonnegative(),
|
|
63794
|
+
omitted_routes: external_exports.number().int().nonnegative(),
|
|
63795
|
+
coverage: external_exports.enum(["occurrence_metadata", "retained_samples"])
|
|
63796
|
+
});
|
|
63797
|
+
function normalizeResourceRoute(value) {
|
|
63798
|
+
if (typeof value !== "string" || !value.startsWith("/") || value.startsWith("//") || value.length > 4096)
|
|
63799
|
+
return null;
|
|
63800
|
+
const path = value.split(/[?#]/, 1)[0];
|
|
63801
|
+
if (/[\u0000-\u0020\u007f\\]/.test(path)) return null;
|
|
63802
|
+
const segments = path.split("/").filter(Boolean).map((segment) => {
|
|
63803
|
+
let decoded;
|
|
63804
|
+
try {
|
|
63805
|
+
decoded = decodeURIComponent(segment);
|
|
63806
|
+
} catch {
|
|
63807
|
+
return "{param}";
|
|
63808
|
+
}
|
|
63809
|
+
if (decoded === "{param}" || /^:[A-Za-z_][A-Za-z_0-9]*$/.test(decoded)) return "{param}";
|
|
63810
|
+
return /^\d+$/.test(decoded) || /^[a-f0-9-]{16,}$/i.test(decoded) || /^[A-Za-z0-9_-]{24,}$/.test(decoded) || decoded.length >= 16 && /[A-Za-z]/.test(decoded) && /\d/.test(decoded) || /[@/\\\u0000-\u0020\u007f]/.test(decoded) ? "{param}" : segment;
|
|
63811
|
+
});
|
|
63812
|
+
const route = `/${segments.join("/")}`;
|
|
63813
|
+
return route.length <= 1024 ? route : null;
|
|
63814
|
+
}
|
|
63815
|
+
function summarizeResourceRoutes(routes, occurrenceCount) {
|
|
63816
|
+
const counts = /* @__PURE__ */ new Map();
|
|
63817
|
+
for (const raw of routes) {
|
|
63818
|
+
const route = normalizeResourceRoute(raw);
|
|
63819
|
+
if (route !== null) counts.set(route, (counts.get(route) ?? 0) + 1);
|
|
63820
|
+
}
|
|
63821
|
+
const items = [...counts].map(([route, occurrences]) => ({ route, occurrences })).sort(
|
|
63822
|
+
(a, b) => b.occurrences - a.occurrences || (a.route < b.route ? -1 : a.route > b.route ? 1 : 0)
|
|
63823
|
+
);
|
|
63824
|
+
const recorded = items.reduce((total, item) => total + item.occurrences, 0);
|
|
63825
|
+
return {
|
|
63826
|
+
items: items.slice(0, 20),
|
|
63827
|
+
recorded_occurrences: recorded,
|
|
63828
|
+
unattributed_occurrences: Math.max(0, occurrenceCount - recorded),
|
|
63829
|
+
omitted_routes: Math.max(0, items.length - 20),
|
|
63830
|
+
coverage: "retained_samples"
|
|
63831
|
+
};
|
|
63832
|
+
}
|
|
63833
|
+
|
|
63834
|
+
// ../../packages/shared-types/src/browser-resource-context.ts
|
|
63835
|
+
var BrowserResourceContextSchema = external_exports.object({
|
|
63836
|
+
version: external_exports.literal(1),
|
|
63837
|
+
host: external_exports.string().max(255).nullable(),
|
|
63838
|
+
path: external_exports.string().max(1024),
|
|
63839
|
+
type: external_exports.string().nullable(),
|
|
63840
|
+
first_party: external_exports.boolean().nullable(),
|
|
63841
|
+
role: external_exports.enum([
|
|
63842
|
+
"analytics",
|
|
63843
|
+
"advertising",
|
|
63844
|
+
"tag_manager",
|
|
63845
|
+
"authentication",
|
|
63846
|
+
"application_asset",
|
|
63847
|
+
"unknown"
|
|
63848
|
+
]),
|
|
63849
|
+
provider: external_exports.string().nullable(),
|
|
63850
|
+
title: external_exports.string(),
|
|
63851
|
+
optional_candidate: external_exports.boolean(),
|
|
63852
|
+
diagnosis: external_exports.string(),
|
|
63853
|
+
routes: BrowserResourceRoutesSchema
|
|
63854
|
+
});
|
|
63855
|
+
|
|
63789
63856
|
// ../../packages/shared-types/src/tier-capabilities.ts
|
|
63790
63857
|
var TIER_CAPABILITIES = {
|
|
63791
63858
|
free: {
|
|
@@ -64620,6 +64687,93 @@ var CaptureRulesFileSchema = external_exports.object({
|
|
|
64620
64687
|
rules: external_exports.array(CaptureRuleSchema)
|
|
64621
64688
|
});
|
|
64622
64689
|
|
|
64690
|
+
// ../../packages/shared-types/src/browser-resource.ts
|
|
64691
|
+
function record(value) {
|
|
64692
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
64693
|
+
}
|
|
64694
|
+
function httpUrl(value, base2) {
|
|
64695
|
+
if (typeof value !== "string" || value.length === 0 || value.length > 4096 || /[\u0000-\u0020\u007f]/.test(value))
|
|
64696
|
+
return null;
|
|
64697
|
+
try {
|
|
64698
|
+
const url = base2 === void 0 ? new URL(value) : new URL(value, base2);
|
|
64699
|
+
return url.protocol === "http:" || url.protocol === "https:" ? url : null;
|
|
64700
|
+
} catch {
|
|
64701
|
+
return null;
|
|
64702
|
+
}
|
|
64703
|
+
}
|
|
64704
|
+
function browserResourceLocation(source, page) {
|
|
64705
|
+
if (typeof source !== "string") return null;
|
|
64706
|
+
const pageUrl = httpUrl(page);
|
|
64707
|
+
const url = httpUrl(source, pageUrl ?? void 0);
|
|
64708
|
+
if (url !== null) {
|
|
64709
|
+
if (url.pathname.length > 1024 || url.hostname.length > 255) return null;
|
|
64710
|
+
return {
|
|
64711
|
+
host: url.hostname.toLowerCase(),
|
|
64712
|
+
path: url.pathname || "/",
|
|
64713
|
+
first_party: pageUrl === null ? null : url.origin === pageUrl.origin
|
|
64714
|
+
};
|
|
64715
|
+
}
|
|
64716
|
+
if (source.startsWith("/") && !source.startsWith("//") && !source.includes("\\") && !/[\u0000-\u0020\u007f]/.test(source)) {
|
|
64717
|
+
const path = source.split(/[?#]/, 1)[0];
|
|
64718
|
+
if (path.length <= 1024) return { host: null, path, first_party: true };
|
|
64719
|
+
}
|
|
64720
|
+
return null;
|
|
64721
|
+
}
|
|
64722
|
+
function describeBrowserResource(value) {
|
|
64723
|
+
const event = record(value);
|
|
64724
|
+
if (event?.["kind"] !== "resource_error") return null;
|
|
64725
|
+
const target = record(event["target"]);
|
|
64726
|
+
const page = record(event["page"]);
|
|
64727
|
+
const location = browserResourceLocation(
|
|
64728
|
+
target?.["source_url"] ?? event["file_name"],
|
|
64729
|
+
page?.["url"]
|
|
64730
|
+
);
|
|
64731
|
+
if (location === null) return null;
|
|
64732
|
+
const tag2 = typeof target?.["tag_name"] === "string" ? target["tag_name"].toLowerCase() : null;
|
|
64733
|
+
const type = tag2 !== null && [
|
|
64734
|
+
"script",
|
|
64735
|
+
"link",
|
|
64736
|
+
"img",
|
|
64737
|
+
"audio",
|
|
64738
|
+
"video",
|
|
64739
|
+
"source",
|
|
64740
|
+
"iframe",
|
|
64741
|
+
"object",
|
|
64742
|
+
"embed",
|
|
64743
|
+
"input"
|
|
64744
|
+
].includes(tag2) ? tag2 : null;
|
|
64745
|
+
let role = location.first_party === true ? "application_asset" : "unknown";
|
|
64746
|
+
let provider = null;
|
|
64747
|
+
if (type === "script") {
|
|
64748
|
+
if (location.host === "www.googletagmanager.com" && location.path === "/gtm.js") {
|
|
64749
|
+
provider = "Google Tag Manager";
|
|
64750
|
+
role = "tag_manager";
|
|
64751
|
+
} else if (location.host === "connect.facebook.net" && /^\/[a-z]{2}_[A-Z]{2}\/fbevents\.js$/.test(location.path)) {
|
|
64752
|
+
provider = "Meta Pixel";
|
|
64753
|
+
role = "advertising";
|
|
64754
|
+
} else if (location.host === "www.clarity.ms" && /^\/tag\/[A-Za-z0-9]+$/.test(location.path)) {
|
|
64755
|
+
provider = "Microsoft Clarity";
|
|
64756
|
+
role = "analytics";
|
|
64757
|
+
} else if (location.host === "accounts.google.com" && location.path === "/gsi/client") {
|
|
64758
|
+
provider = "Google sign-in";
|
|
64759
|
+
role = "authentication";
|
|
64760
|
+
}
|
|
64761
|
+
}
|
|
64762
|
+
const file = location.path.split("/").filter(Boolean).at(-1) ?? location.path;
|
|
64763
|
+
const kind = type === "img" ? "Image" : type === "script" || /\.m?js$/i.test(file) ? "JavaScript asset" : "Resource";
|
|
64764
|
+
return {
|
|
64765
|
+
...location,
|
|
64766
|
+
type,
|
|
64767
|
+
role,
|
|
64768
|
+
provider,
|
|
64769
|
+
title: provider !== null ? `${provider} script failed to load` : `${kind} failed to load: ${file}${location.host === null ? "" : ` (${location.host})`}`,
|
|
64770
|
+
optional_candidate: event["opaque"] === true && location.first_party !== true && ["analytics", "advertising", "tag_manager"].includes(role)
|
|
64771
|
+
};
|
|
64772
|
+
}
|
|
64773
|
+
function browserResourceDiagnosis(resource) {
|
|
64774
|
+
return resource?.optional_candidate === true ? "The browser reported that this script failed to load. Possibly blocked by privacy tools; network, CSP or provider failures are also possible. The captured event does not identify the cause." : "The browser reported that this resource failed to load. The captured event does not identify the cause or establish whether application functionality was affected.";
|
|
64775
|
+
}
|
|
64776
|
+
|
|
64623
64777
|
// ../../packages/shared-types/src/capture-rule-evaluation.ts
|
|
64624
64778
|
var CaptureRuleEvaluationUrlSchema = external_exports.object({
|
|
64625
64779
|
host: external_exports.string().min(1).transform((value) => value.toLowerCase()).optional(),
|
|
@@ -64687,6 +64841,7 @@ var CaptureRuleSuggestionSchema = external_exports.object({
|
|
|
64687
64841
|
rule: CaptureRuleCreateSchema
|
|
64688
64842
|
});
|
|
64689
64843
|
var CaptureRuleSuggestionsResponseSchema = external_exports.object({
|
|
64844
|
+
access_mode: external_exports.enum(["manage", "preview"]).optional(),
|
|
64690
64845
|
suggestions: external_exports.array(CaptureRuleSuggestionSchema),
|
|
64691
64846
|
bundle_status: external_exports.enum(["ready", "pending", "failed"]).optional(),
|
|
64692
64847
|
bundle_reason: external_exports.string().nullable().optional()
|
|
@@ -65182,6 +65337,14 @@ function looksSensitiveCustomDimensionValue(value) {
|
|
|
65182
65337
|
return /https?:\/\//i.test(value) || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value) || /\bBearer\s+[A-Za-z0-9._~+/=-]+/i.test(value) || /\b(?:token|password|secret|api_key)=/i.test(value);
|
|
65183
65338
|
}
|
|
65184
65339
|
|
|
65340
|
+
// ../../packages/shared-types/src/frontend-severity.ts
|
|
65341
|
+
function inferFrontendExceptionSeverity(event) {
|
|
65342
|
+
const browserEvent = event.payload.browser_event;
|
|
65343
|
+
if (browserEvent?.opaque === true)
|
|
65344
|
+
return browserEvent.kind === "resource_error" ? "medium" : "low";
|
|
65345
|
+
return "high";
|
|
65346
|
+
}
|
|
65347
|
+
|
|
65185
65348
|
// ../../packages/shared-types/src/analytics-product.ts
|
|
65186
65349
|
var AnalyticsOpportunityStatusValues = ["open", "resolved", "snoozed"];
|
|
65187
65350
|
var AnalyticsOpportunityStatusSchema = external_exports.enum(AnalyticsOpportunityStatusValues);
|
|
@@ -65756,6 +65919,7 @@ var ContextDeviceSchema = external_exports.object({
|
|
|
65756
65919
|
color_scheme_preference: external_exports.enum(["light", "dark", "no-preference"]).nullable()
|
|
65757
65920
|
});
|
|
65758
65921
|
var BundleContextSchema = external_exports.object({
|
|
65922
|
+
resource_failure: BrowserResourceContextSchema.optional(),
|
|
65759
65923
|
error: ContextErrorSchema.nullable().optional(),
|
|
65760
65924
|
request: ContextRequestSchema.nullable().optional(),
|
|
65761
65925
|
response: ContextResponseSchema.nullable().optional(),
|
|
@@ -65980,6 +66144,15 @@ function buildSkill() {
|
|
|
65980
66144
|
"- Scope frontend noise by structured evidence such as service, environment, `browser_event_kind`, `browser_event_opaque`, `client_kind`, `bot_family`, and message fields. Do not broadly demote generic `Unhandled promise rejection` incidents without bot-scoped or otherwise narrow evidence.",
|
|
65981
66145
|
"- For expected or intentionally promoted 4xx responses on known routes, use capture-policy client-error path rules instead of promoting all client errors: `debugbundle capture-policy set --client-error-path-rule <status=/path/*@GET>`.",
|
|
65982
66146
|
"",
|
|
66147
|
+
"### Browser resource failures",
|
|
66148
|
+
"",
|
|
66149
|
+
"- Inspect the primary failure and routes: one resource can span pages, route coverage may be incomplete, and historical incidents stay separate. Related tracker evidence does not explain an application exception.",
|
|
66150
|
+
'- If the cause is unknown, say "possibly blocked by privacy tools." Network/CSP/provider failures remain possible; provider recognition proves neither Pi-hole blocking nor optionality.',
|
|
66151
|
+
"- Review exact host/path, service, environment and opaque resource-error scope; never widen to a whole host. Google sign-in, app assets and unknown dependencies have no automatic resource noise recommendation.",
|
|
66152
|
+
"- For confirmed optional dependencies, context (demote) retains diagnostics without new incidents/alerts/automation and may remain billable. Drop discards future matches; choose it only when evidence has no diagnostic value. Explain the tradeoff; neither deletes history. Use the returned suggestion ID.",
|
|
66153
|
+
"- Check existing/disabled rules. Empty suggestions or pending/failed bundles do not justify broader rules. Applying requires user authorization and owner/admin access; preview is read-only. Verify subsequent matching and protected captures before claiming improvement; live tests need authorization.",
|
|
66154
|
+
"- The official OpenAI connection cannot suggest or apply rules. When it is the only connection, review returned evidence and hand off through a returned safe dashboard URL; never invent tools or switch credentials.",
|
|
66155
|
+
"",
|
|
65983
66156
|
"## Notification Delivery",
|
|
65984
66157
|
"",
|
|
65985
66158
|
"When notification or automation delivery is the reported failure, inspect configuration and delivery records before changing incident logic.",
|
|
@@ -66087,6 +66260,7 @@ function buildCliReference() {
|
|
|
66087
66260
|
"- `debugbundle capture-policy set [--project <id>] --client-error-path-rule <404=/path/*@GET,POST> [--json]`",
|
|
66088
66261
|
"",
|
|
66089
66262
|
"Use capture-rule suggestions for repeated operational noise after inspecting an incident bundle. Use capture-policy client-error path rules for route-scoped 4xx incidents instead of promoting all client errors.",
|
|
66263
|
+
"For browser resource failures, follow the skill's Browser resource failures guidance. Use the current response's suggestion ID, inspect `bundle_status`, `access_mode` and existing-rule state, and review the complete matcher before applying.",
|
|
66090
66264
|
"",
|
|
66091
66265
|
"## Probes",
|
|
66092
66266
|
"",
|
|
@@ -66235,6 +66409,7 @@ function buildMcpReference() {
|
|
|
66235
66409
|
"- `get_capture_policy`, `update_capture_policy` \u2014 review or update capture policy, including path-scoped client-error incident rules.",
|
|
66236
66410
|
"",
|
|
66237
66411
|
"Use these tools for repeated low-value operational noise only after inspecting incident evidence. Keep frontend suppression scoped by structured browser and client signals, and use path-scoped capture policy for known 4xx routes.",
|
|
66412
|
+
"For browser resource failures, follow the skill's Browser resource failures guidance and use the suggestion ID returned by the server. These management tools belong to the member-authenticated MCP surface; the official OpenAI connection is read-only and cannot suggest or apply capture rules.",
|
|
66238
66413
|
"",
|
|
66239
66414
|
"## Product Analytics Tools",
|
|
66240
66415
|
"",
|
|
@@ -66430,6 +66605,43 @@ function buildSkillEvals() {
|
|
|
66430
66605
|
"Use capture-policy path rules for known route-scoped 4xx incidents."
|
|
66431
66606
|
]
|
|
66432
66607
|
},
|
|
66608
|
+
{
|
|
66609
|
+
name: "browser_resource_noise_review",
|
|
66610
|
+
prompt: "GTM failed on four routes. The owner says analytics is optional and asks to keep useful diagnostics without repeated alerts. The suggestion response offers resource_context and resource_drop with exact host/path/service/environment matchers. Explain and apply the appropriate authorized choice.",
|
|
66611
|
+
expected_behavior: [
|
|
66612
|
+
"Inspect the primary failure and bounded route coverage; do not count each route as a separate application defect.",
|
|
66613
|
+
"Describe privacy blocking as possible, not proven; do not diagnose Pi-hole.",
|
|
66614
|
+
"Review the exact matcher and use the returned context suggestion ID; explain retained evidence and possible paid usage.",
|
|
66615
|
+
"Verify the returned rule without claiming historical incidents were removed or live noise reduction was already observed."
|
|
66616
|
+
]
|
|
66617
|
+
},
|
|
66618
|
+
{
|
|
66619
|
+
name: "protected_resource_noise_review",
|
|
66620
|
+
prompt: "A checkout TypeError has related GTM evidence. Separate incidents show Google sign-in and an unknown script failing. The user asks whether ignoring all Google or third-party hosts would clean this up.",
|
|
66621
|
+
expected_behavior: [
|
|
66622
|
+
"Keep the primary checkout exception separate from related tracker evidence.",
|
|
66623
|
+
"Do not broaden rules to whole hosts or infer that sign-in, app assets or unknown dependencies are optional.",
|
|
66624
|
+
"Inspect evidence and available suggestions before proposing any narrowly scoped change."
|
|
66625
|
+
]
|
|
66626
|
+
},
|
|
66627
|
+
{
|
|
66628
|
+
name: "unavailable_resource_noise_suggestions",
|
|
66629
|
+
prompt: "Resource suggestions are pending or empty, the current member has preview access, and a matching rule is disabled. The user asks why the resource still opens incidents.",
|
|
66630
|
+
expected_behavior: [
|
|
66631
|
+
"Explain the missing evidence and access limits without inventing a rule or bypassing authorization.",
|
|
66632
|
+
"Inspect the disabled rule; do not assume it is active, create a duplicate or silently enable it.",
|
|
66633
|
+
"Do not claim noise was reduced or resolve historical incidents based solely on a policy proposal."
|
|
66634
|
+
]
|
|
66635
|
+
},
|
|
66636
|
+
{
|
|
66637
|
+
name: "readonly_resource_noise_handoff",
|
|
66638
|
+
prompt: "Only the official read-only OpenAI connection is available. The user asks to ignore recurring tracker failures.",
|
|
66639
|
+
expected_behavior: [
|
|
66640
|
+
"Inspect only available incident evidence; distinguish possible privacy blocking from a proven cause.",
|
|
66641
|
+
"Explain that this connection cannot fetch capture-rule suggestions or apply rules; do not invent a management tool or switch credentials.",
|
|
66642
|
+
"Use a returned safe dashboard URL for a reviewed handoff when available, and never claim a rule was applied."
|
|
66643
|
+
]
|
|
66644
|
+
},
|
|
66433
66645
|
{
|
|
66434
66646
|
name: "operational_controls_guidance",
|
|
66435
66647
|
prompt: "The user reports missing webhook deliveries and asks whether probes or alerts are available. Confirm the skill points the agent to the relevant operational controls and docs.",
|
|
@@ -84218,8 +84430,57 @@ var WINDOW_RETENTION_SECONDS = WINDOW_24H_SECONDS + WINDOW_1H_SECONDS;
|
|
|
84218
84430
|
// ../../packages/storage/src/ingestion-rate-limiter.ts
|
|
84219
84431
|
var import_ioredis3 = __toESM(require_built3(), 1);
|
|
84220
84432
|
|
|
84221
|
-
// ../../packages/event-normalizer/src/
|
|
84222
|
-
var
|
|
84433
|
+
// ../../packages/event-normalizer/src/fingerprints.ts
|
|
84434
|
+
var import_node_crypto4 = require("node:crypto");
|
|
84435
|
+
var FINGERPRINT_VERSION = "v2";
|
|
84436
|
+
var RESOURCE_FINGERPRINT_VERSION = "v3";
|
|
84437
|
+
function fingerprintVersion(event) {
|
|
84438
|
+
return event.resource_type != null ? RESOURCE_FINGERPRINT_VERSION : FINGERPRINT_VERSION;
|
|
84439
|
+
}
|
|
84440
|
+
function stableJson(value) {
|
|
84441
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
84442
|
+
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
|
84443
|
+
const object = value;
|
|
84444
|
+
return `{${Object.keys(object).sort().map((key) => `${JSON.stringify(key)}:${stableJson(object[key])}`).join(",")}}`;
|
|
84445
|
+
}
|
|
84446
|
+
function fingerprint(event) {
|
|
84447
|
+
const canonical = event.resource_type != null ? {
|
|
84448
|
+
// A concrete resource is the grouping unit, not proof of a common underlying cause.
|
|
84449
|
+
browser_event_kind: "resource_error",
|
|
84450
|
+
resource_host: event.resource_host,
|
|
84451
|
+
resource_path: event.resource_path,
|
|
84452
|
+
resource_type: event.resource_type,
|
|
84453
|
+
environment: event.environment,
|
|
84454
|
+
fingerprint_version: RESOURCE_FINGERPRINT_VERSION
|
|
84455
|
+
} : {
|
|
84456
|
+
// Preserve exact historical bytes for every non-resource event and explicit legacy normalization.
|
|
84457
|
+
error_type: event.error_type,
|
|
84458
|
+
normalized_message: event.normalized_message,
|
|
84459
|
+
top_frames: event.top_frames,
|
|
84460
|
+
route_template: event.route_template,
|
|
84461
|
+
browser_event_kind: event.browser_event_kind,
|
|
84462
|
+
resource_host: event.resource_host,
|
|
84463
|
+
resource_path: event.resource_path,
|
|
84464
|
+
http_method: event.http_method,
|
|
84465
|
+
http_status: event.http_status,
|
|
84466
|
+
environment: event.environment
|
|
84467
|
+
};
|
|
84468
|
+
return (0, import_node_crypto4.createHash)("sha256").update(stableJson(canonical)).digest("hex");
|
|
84469
|
+
}
|
|
84470
|
+
function inferMatchedFields(event) {
|
|
84471
|
+
if (event.resource_type != null)
|
|
84472
|
+
return ["environment", "browser_event_kind", "resource_host", "resource_path", "resource_type"];
|
|
84473
|
+
const fields = ["environment", "normalized_message"];
|
|
84474
|
+
if (event.error_type !== null) fields.push("error_type");
|
|
84475
|
+
if (event.route_template !== null) fields.push("route_template");
|
|
84476
|
+
if (event.top_frames.length > 0) fields.push("top_frames");
|
|
84477
|
+
if (event.browser_event_kind != null) fields.push("browser_event_kind");
|
|
84478
|
+
if (event.resource_host != null) fields.push("resource_host");
|
|
84479
|
+
if (event.resource_path != null) fields.push("resource_path");
|
|
84480
|
+
if (event.http_method !== null) fields.push("http_method");
|
|
84481
|
+
if (event.http_status !== null) fields.push("http_status");
|
|
84482
|
+
return fields;
|
|
84483
|
+
}
|
|
84223
84484
|
|
|
84224
84485
|
// ../../packages/redaction/src/index.ts
|
|
84225
84486
|
var DEFAULT_SENSITIVE_KEYS = [
|
|
@@ -84318,7 +84579,7 @@ function redact(payload2, options) {
|
|
|
84318
84579
|
}
|
|
84319
84580
|
|
|
84320
84581
|
// ../../packages/event-normalizer/src/mobile-event-compatibility.ts
|
|
84321
|
-
var
|
|
84582
|
+
var import_node_crypto5 = require("node:crypto");
|
|
84322
84583
|
var MOBILE_SDKS = /* @__PURE__ */ new Set(["@debugbundle/sdk-android", "@debugbundle/sdk-swift"]);
|
|
84323
84584
|
function isRecord3(candidate) {
|
|
84324
84585
|
return typeof candidate === "object" && candidate !== null && !Array.isArray(candidate);
|
|
@@ -84345,8 +84606,8 @@ function readInteger(candidate) {
|
|
|
84345
84606
|
function readBoolean2(candidate) {
|
|
84346
84607
|
return typeof candidate === "boolean" ? candidate : null;
|
|
84347
84608
|
}
|
|
84348
|
-
function readField(
|
|
84349
|
-
return
|
|
84609
|
+
function readField(record2, snakeCase, camelCase) {
|
|
84610
|
+
return record2[snakeCase] ?? record2[camelCase];
|
|
84350
84611
|
}
|
|
84351
84612
|
function stableValue(candidate) {
|
|
84352
84613
|
if (Array.isArray(candidate)) {
|
|
@@ -84360,7 +84621,7 @@ function stableValue(candidate) {
|
|
|
84360
84621
|
);
|
|
84361
84622
|
}
|
|
84362
84623
|
function deterministicEventId(candidate) {
|
|
84363
|
-
const digest2 = (0,
|
|
84624
|
+
const digest2 = (0, import_node_crypto5.createHash)("sha256").update(JSON.stringify(stableValue(candidate))).digest("hex");
|
|
84364
84625
|
const chars = digest2.slice(0, 32).split("");
|
|
84365
84626
|
chars[12] = "5";
|
|
84366
84627
|
chars[16] = ["8", "9", "a", "b"][Number.parseInt(chars[16] ?? "0", 16) % 4] ?? "8";
|
|
@@ -84726,7 +84987,6 @@ function normalizeJavaTimerMessage(message3) {
|
|
|
84726
84987
|
}
|
|
84727
84988
|
|
|
84728
84989
|
// ../../packages/event-normalizer/src/index.ts
|
|
84729
|
-
var FINGERPRINT_VERSION = "v2";
|
|
84730
84990
|
var PAYLOAD_ALLOWED_KEYS = {
|
|
84731
84991
|
backend_exception: /* @__PURE__ */ new Set([
|
|
84732
84992
|
"name",
|
|
@@ -84909,34 +85169,6 @@ function normalizeCompatibleEventCandidate(candidate) {
|
|
|
84909
85169
|
}
|
|
84910
85170
|
return event;
|
|
84911
85171
|
}
|
|
84912
|
-
function inferMatchedFields(event) {
|
|
84913
|
-
const matchedFields = ["environment", "normalized_message"];
|
|
84914
|
-
if (event.error_type !== null) {
|
|
84915
|
-
matchedFields.push("error_type");
|
|
84916
|
-
}
|
|
84917
|
-
if (event.route_template !== null) {
|
|
84918
|
-
matchedFields.push("route_template");
|
|
84919
|
-
}
|
|
84920
|
-
if (event.top_frames.length > 0) {
|
|
84921
|
-
matchedFields.push("top_frames");
|
|
84922
|
-
}
|
|
84923
|
-
if (event.browser_event_kind != null) {
|
|
84924
|
-
matchedFields.push("browser_event_kind");
|
|
84925
|
-
}
|
|
84926
|
-
if (event.resource_host != null) {
|
|
84927
|
-
matchedFields.push("resource_host");
|
|
84928
|
-
}
|
|
84929
|
-
if (event.resource_path != null) {
|
|
84930
|
-
matchedFields.push("resource_path");
|
|
84931
|
-
}
|
|
84932
|
-
if (event.http_method !== null) {
|
|
84933
|
-
matchedFields.push("http_method");
|
|
84934
|
-
}
|
|
84935
|
-
if (event.http_status !== null) {
|
|
84936
|
-
matchedFields.push("http_status");
|
|
84937
|
-
}
|
|
84938
|
-
return matchedFields;
|
|
84939
|
-
}
|
|
84940
85172
|
var UUID_PATTERN = /\b[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}\b/gi;
|
|
84941
85173
|
var EMAIL_PATTERN = /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/gi;
|
|
84942
85174
|
var ISO_TIMESTAMP_PATTERN = /\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z\b/g;
|
|
@@ -85140,22 +85372,10 @@ function normalizeResourceIdentity(value) {
|
|
|
85140
85372
|
};
|
|
85141
85373
|
}
|
|
85142
85374
|
}
|
|
85143
|
-
function stableJson(value) {
|
|
85144
|
-
if (value === null || typeof value !== "object") {
|
|
85145
|
-
return JSON.stringify(value);
|
|
85146
|
-
}
|
|
85147
|
-
if (Array.isArray(value)) {
|
|
85148
|
-
return `[${value.map((entry) => stableJson(entry)).join(",")}]`;
|
|
85149
|
-
}
|
|
85150
|
-
const record = value;
|
|
85151
|
-
const keys2 = Object.keys(record).sort();
|
|
85152
|
-
const pairs = keys2.map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`);
|
|
85153
|
-
return `{${pairs.join(",")}}`;
|
|
85154
|
-
}
|
|
85155
85375
|
function validateEvent(candidate) {
|
|
85156
85376
|
return EventEnvelopeSchema.safeParse(normalizeCompatibleEventCandidate(candidate));
|
|
85157
85377
|
}
|
|
85158
|
-
function normalizeEvent(event, version2 =
|
|
85378
|
+
function normalizeEvent(event, version2 = RESOURCE_FINGERPRINT_VERSION) {
|
|
85159
85379
|
const redactedPayload = redact(event.payload).redacted;
|
|
85160
85380
|
if (event.event_type === "backend_exception") {
|
|
85161
85381
|
return {
|
|
@@ -85209,6 +85429,8 @@ function normalizeEvent(event, version2 = FINGERPRINT_VERSION) {
|
|
|
85209
85429
|
const browserEvent = event.payload.browser_event;
|
|
85210
85430
|
const resourceIdentity = browserEvent?.kind === "resource_error" ? normalizeResourceIdentity(browserEvent.target?.source_url ?? browserEvent.file_name) : { host: null, path: null };
|
|
85211
85431
|
const topFrames = browserEvent?.opaque === true ? [] : selectTopFrames(event.payload.stack);
|
|
85432
|
+
const resource = describeBrowserResource(browserEvent);
|
|
85433
|
+
const concreteResource = version2 === RESOURCE_FINGERPRINT_VERSION && browserEvent?.opaque === true && resource?.host != null && resource.type !== null;
|
|
85212
85434
|
return {
|
|
85213
85435
|
event_type: event.event_type,
|
|
85214
85436
|
environment: event.service.environment,
|
|
@@ -85219,8 +85441,10 @@ function normalizeEvent(event, version2 = FINGERPRINT_VERSION) {
|
|
|
85219
85441
|
http_status: null,
|
|
85220
85442
|
top_frames: topFrames,
|
|
85221
85443
|
browser_event_kind: browserEvent?.kind ?? null,
|
|
85222
|
-
resource_host: resourceIdentity.host,
|
|
85223
|
-
resource_path: resourceIdentity.path,
|
|
85444
|
+
resource_host: concreteResource ? resource.host : resourceIdentity.host,
|
|
85445
|
+
resource_path: concreteResource ? resource.path : resourceIdentity.path,
|
|
85446
|
+
...concreteResource ? { resource_type: resource.type } : {},
|
|
85447
|
+
...resource === null ? {} : { incident_title: resource.title },
|
|
85224
85448
|
payload: redactedPayload
|
|
85225
85449
|
};
|
|
85226
85450
|
}
|
|
@@ -85239,21 +85463,6 @@ function normalizeEvent(event, version2 = FINGERPRINT_VERSION) {
|
|
|
85239
85463
|
payload: redactedPayload
|
|
85240
85464
|
};
|
|
85241
85465
|
}
|
|
85242
|
-
function fingerprint(event) {
|
|
85243
|
-
const canonical = {
|
|
85244
|
-
error_type: event.error_type,
|
|
85245
|
-
normalized_message: event.normalized_message,
|
|
85246
|
-
top_frames: event.top_frames,
|
|
85247
|
-
route_template: event.route_template,
|
|
85248
|
-
browser_event_kind: event.browser_event_kind,
|
|
85249
|
-
resource_host: event.resource_host,
|
|
85250
|
-
resource_path: event.resource_path,
|
|
85251
|
-
http_method: event.http_method,
|
|
85252
|
-
http_status: event.http_status,
|
|
85253
|
-
environment: event.environment
|
|
85254
|
-
};
|
|
85255
|
-
return (0, import_node_crypto5.createHash)("sha256").update(stableJson(canonical)).digest("hex");
|
|
85256
|
-
}
|
|
85257
85466
|
var INCIDENT_LOG_LEVELS = /* @__PURE__ */ new Set(["error", "fatal", "critical"]);
|
|
85258
85467
|
function getRequestResponseStatus(payload2) {
|
|
85259
85468
|
const status = payload2?.["response_status"];
|
|
@@ -86080,6 +86289,192 @@ var OPENAI_OAUTH_BOOTSTRAP_STATEMENTS = [
|
|
|
86080
86289
|
`CREATE INDEX oauth_provider_artifacts_expires_idx ON oauth_provider_artifacts (expires_at, model, provider_id_hash)`
|
|
86081
86290
|
];
|
|
86082
86291
|
|
|
86292
|
+
// ../../packages/storage/src/storage-bootstrap-incident-statements.ts
|
|
86293
|
+
var STORAGE_BOOTSTRAP_INCIDENT_STATEMENTS = [
|
|
86294
|
+
`
|
|
86295
|
+
CREATE TABLE incidents (
|
|
86296
|
+
id uuid PRIMARY KEY,
|
|
86297
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
86298
|
+
service_id uuid REFERENCES services(id) ON DELETE SET NULL,
|
|
86299
|
+
environment text NOT NULL DEFAULT 'production',
|
|
86300
|
+
fingerprint text NOT NULL,
|
|
86301
|
+
fingerprint_version text NOT NULL DEFAULT 'v1',
|
|
86302
|
+
title text NOT NULL,
|
|
86303
|
+
severity text NOT NULL,
|
|
86304
|
+
status text NOT NULL DEFAULT 'open',
|
|
86305
|
+
first_seen_at timestamptz NOT NULL,
|
|
86306
|
+
last_seen_at timestamptz NOT NULL,
|
|
86307
|
+
occurrence_count integer NOT NULL DEFAULT 1,
|
|
86308
|
+
matched_fields text[],
|
|
86309
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
86310
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
86311
|
+
regressed_at timestamptz,
|
|
86312
|
+
spike_detected_at timestamptz,
|
|
86313
|
+
frequency_occurrences_1m integer,
|
|
86314
|
+
frequency_occurrences_5m integer,
|
|
86315
|
+
frequency_occurrences_1h integer,
|
|
86316
|
+
frequency_occurrences_24h integer,
|
|
86317
|
+
frequency_baseline_1h_per_5m double precision,
|
|
86318
|
+
frequency_spike_ratio_5m_to_1h double precision,
|
|
86319
|
+
frequency_has_sufficient_baseline boolean,
|
|
86320
|
+
frequency_is_spiking boolean,
|
|
86321
|
+
frequency_snapshot_at timestamptz,
|
|
86322
|
+
latest_deployment_id uuid REFERENCES deployments(id) ON DELETE SET NULL,
|
|
86323
|
+
bundle_generation_number integer NOT NULL DEFAULT 0,
|
|
86324
|
+
bundle_created_at timestamptz,
|
|
86325
|
+
bundle_updated_at timestamptz,
|
|
86326
|
+
bundle_source_event_id uuid,
|
|
86327
|
+
bundle_source_occurred_at timestamptz,
|
|
86328
|
+
bundle_trigger text,
|
|
86329
|
+
bundle_failure_reason text,
|
|
86330
|
+
resolved_at timestamptz,
|
|
86331
|
+
resolved_by_member_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
86332
|
+
UNIQUE (project_id, environment, service_id, fingerprint)
|
|
86333
|
+
)
|
|
86334
|
+
`,
|
|
86335
|
+
`
|
|
86336
|
+
CREATE TABLE processed_events (
|
|
86337
|
+
event_id uuid PRIMARY KEY,
|
|
86338
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
86339
|
+
event_type text NOT NULL,
|
|
86340
|
+
fingerprint text NOT NULL,
|
|
86341
|
+
normalized_message text NOT NULL,
|
|
86342
|
+
processed_at timestamptz NOT NULL DEFAULT now()
|
|
86343
|
+
)
|
|
86344
|
+
`,
|
|
86345
|
+
`
|
|
86346
|
+
CREATE TABLE improvement_opportunities (
|
|
86347
|
+
id uuid PRIMARY KEY,
|
|
86348
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
86349
|
+
service_id uuid REFERENCES services(id) ON DELETE SET NULL,
|
|
86350
|
+
service_name text NOT NULL,
|
|
86351
|
+
environment text NOT NULL DEFAULT 'production',
|
|
86352
|
+
kind text NOT NULL,
|
|
86353
|
+
status text NOT NULL DEFAULT 'open',
|
|
86354
|
+
severity text NOT NULL,
|
|
86355
|
+
confidence numeric NOT NULL,
|
|
86356
|
+
fingerprint text NOT NULL,
|
|
86357
|
+
title text NOT NULL,
|
|
86358
|
+
summary text NOT NULL,
|
|
86359
|
+
occurrence_count integer NOT NULL DEFAULT 1,
|
|
86360
|
+
evidence jsonb NOT NULL,
|
|
86361
|
+
first_detected_at timestamptz NOT NULL,
|
|
86362
|
+
last_detected_at timestamptz NOT NULL,
|
|
86363
|
+
last_source_event_id uuid,
|
|
86364
|
+
related_incident_ids uuid[] NOT NULL DEFAULT '{}',
|
|
86365
|
+
bundle_generation_number integer NOT NULL DEFAULT 0,
|
|
86366
|
+
bundle_created_at timestamptz,
|
|
86367
|
+
bundle_updated_at timestamptz,
|
|
86368
|
+
bundle_source_event_id uuid,
|
|
86369
|
+
bundle_failure_reason text,
|
|
86370
|
+
resolved_at timestamptz,
|
|
86371
|
+
resolved_by_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
86372
|
+
snoozed_until timestamptz,
|
|
86373
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
86374
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
86375
|
+
UNIQUE (project_id, fingerprint)
|
|
86376
|
+
)
|
|
86377
|
+
`,
|
|
86378
|
+
`
|
|
86379
|
+
CREATE INDEX improvement_opportunities_project_status_detected_idx
|
|
86380
|
+
ON improvement_opportunities (project_id, status, last_detected_at DESC)
|
|
86381
|
+
`,
|
|
86382
|
+
`
|
|
86383
|
+
CREATE INDEX improvement_opportunities_project_kind_detected_idx
|
|
86384
|
+
ON improvement_opportunities (project_id, kind, last_detected_at DESC)
|
|
86385
|
+
`,
|
|
86386
|
+
`
|
|
86387
|
+
CREATE INDEX improvement_opportunities_project_service_env_idx
|
|
86388
|
+
ON improvement_opportunities (project_id, service_id, environment)
|
|
86389
|
+
`,
|
|
86390
|
+
`
|
|
86391
|
+
CREATE TABLE improvement_opportunity_events (
|
|
86392
|
+
improvement_opportunity_id uuid NOT NULL REFERENCES improvement_opportunities(id) ON DELETE CASCADE,
|
|
86393
|
+
event_id uuid NOT NULL,
|
|
86394
|
+
event_type text NOT NULL,
|
|
86395
|
+
occurred_at timestamptz NOT NULL,
|
|
86396
|
+
PRIMARY KEY (improvement_opportunity_id, event_id)
|
|
86397
|
+
)
|
|
86398
|
+
`,
|
|
86399
|
+
`
|
|
86400
|
+
CREATE INDEX improvement_opportunity_events_detected_idx
|
|
86401
|
+
ON improvement_opportunity_events (improvement_opportunity_id, occurred_at DESC, event_id DESC)
|
|
86402
|
+
`,
|
|
86403
|
+
`
|
|
86404
|
+
CREATE TABLE bundle_generations (
|
|
86405
|
+
id uuid PRIMARY KEY,
|
|
86406
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
86407
|
+
incident_id uuid REFERENCES incidents(id) ON DELETE CASCADE,
|
|
86408
|
+
improvement_opportunity_id uuid REFERENCES improvement_opportunities(id) ON DELETE CASCADE,
|
|
86409
|
+
bundle_type text NOT NULL,
|
|
86410
|
+
generation_number integer NOT NULL,
|
|
86411
|
+
source_event_id uuid NOT NULL,
|
|
86412
|
+
source_occurred_at timestamptz NOT NULL,
|
|
86413
|
+
trigger text NOT NULL,
|
|
86414
|
+
created_at timestamptz NOT NULL,
|
|
86415
|
+
updated_at timestamptz NOT NULL,
|
|
86416
|
+
CHECK (
|
|
86417
|
+
(incident_id IS NOT NULL AND improvement_opportunity_id IS NULL AND bundle_type = 'failure')
|
|
86418
|
+
OR (incident_id IS NULL AND improvement_opportunity_id IS NOT NULL AND bundle_type = 'improvement')
|
|
86419
|
+
)
|
|
86420
|
+
)
|
|
86421
|
+
`,
|
|
86422
|
+
`
|
|
86423
|
+
CREATE UNIQUE INDEX bundle_generations_incident_source_idx
|
|
86424
|
+
ON bundle_generations (incident_id, source_event_id)
|
|
86425
|
+
WHERE incident_id IS NOT NULL
|
|
86426
|
+
`,
|
|
86427
|
+
`
|
|
86428
|
+
CREATE UNIQUE INDEX bundle_generations_improvement_source_idx
|
|
86429
|
+
ON bundle_generations (improvement_opportunity_id, source_event_id)
|
|
86430
|
+
WHERE improvement_opportunity_id IS NOT NULL
|
|
86431
|
+
`,
|
|
86432
|
+
`
|
|
86433
|
+
CREATE INDEX bundle_generations_project_created_idx
|
|
86434
|
+
ON bundle_generations (project_id, created_at DESC, bundle_type)
|
|
86435
|
+
`,
|
|
86436
|
+
`
|
|
86437
|
+
CREATE INDEX bundle_generations_incident_generation_idx
|
|
86438
|
+
ON bundle_generations (incident_id, generation_number DESC)
|
|
86439
|
+
`,
|
|
86440
|
+
`
|
|
86441
|
+
CREATE INDEX bundle_generations_improvement_generation_idx
|
|
86442
|
+
ON bundle_generations (improvement_opportunity_id, generation_number DESC)
|
|
86443
|
+
WHERE improvement_opportunity_id IS NOT NULL
|
|
86444
|
+
`,
|
|
86445
|
+
`
|
|
86446
|
+
CREATE TABLE incident_events (
|
|
86447
|
+
incident_id uuid NOT NULL REFERENCES incidents(id) ON DELETE CASCADE,
|
|
86448
|
+
event_id uuid NOT NULL,
|
|
86449
|
+
event_type text NOT NULL,
|
|
86450
|
+
event_class text NOT NULL DEFAULT 'context_signal',
|
|
86451
|
+
occurred_at timestamptz NOT NULL,
|
|
86452
|
+
is_sampled boolean NOT NULL DEFAULT false,
|
|
86453
|
+
level text,
|
|
86454
|
+
resource_route text,
|
|
86455
|
+
retain_first boolean NOT NULL DEFAULT false,
|
|
86456
|
+
retain_latest boolean NOT NULL DEFAULT false,
|
|
86457
|
+
retain_after_deploy boolean NOT NULL DEFAULT false,
|
|
86458
|
+
retain_highest_severity boolean NOT NULL DEFAULT false,
|
|
86459
|
+
retain_deploy_metadata boolean NOT NULL DEFAULT false,
|
|
86460
|
+
severity_rank integer NOT NULL DEFAULT 0,
|
|
86461
|
+
PRIMARY KEY (incident_id, event_id)
|
|
86462
|
+
)
|
|
86463
|
+
`,
|
|
86464
|
+
`
|
|
86465
|
+
CREATE INDEX incident_events_incident_occurred_event_idx
|
|
86466
|
+
ON incident_events (incident_id, occurred_at DESC, event_id DESC)
|
|
86467
|
+
`,
|
|
86468
|
+
`
|
|
86469
|
+
CREATE INDEX incident_events_incident_level_occurred_event_idx
|
|
86470
|
+
ON incident_events (incident_id, level, occurred_at DESC, event_id DESC)
|
|
86471
|
+
`,
|
|
86472
|
+
`
|
|
86473
|
+
CREATE INDEX incident_events_incident_sampled_idx
|
|
86474
|
+
ON incident_events (incident_id, is_sampled, occurred_at ASC, event_id ASC)
|
|
86475
|
+
`
|
|
86476
|
+
];
|
|
86477
|
+
|
|
86083
86478
|
// ../../packages/storage/src/storage-bootstrap-account-analytics-statements.ts
|
|
86084
86479
|
var STORAGE_BOOTSTRAP_ACCOUNT_ANALYTICS_STATEMENTS = [
|
|
86085
86480
|
`
|
|
@@ -86600,187 +86995,7 @@ var STORAGE_BOOTSTRAP_STATEMENTS = [
|
|
|
86600
86995
|
CREATE INDEX deployments_project_service_env_deployed_idx
|
|
86601
86996
|
ON deployments (project_id, service_id, environment, deployed_at DESC)
|
|
86602
86997
|
`,
|
|
86603
|
-
|
|
86604
|
-
CREATE TABLE incidents (
|
|
86605
|
-
id uuid PRIMARY KEY,
|
|
86606
|
-
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
86607
|
-
service_id uuid REFERENCES services(id) ON DELETE SET NULL,
|
|
86608
|
-
environment text NOT NULL DEFAULT 'production',
|
|
86609
|
-
fingerprint text NOT NULL,
|
|
86610
|
-
fingerprint_version text NOT NULL DEFAULT 'v1',
|
|
86611
|
-
title text NOT NULL,
|
|
86612
|
-
severity text NOT NULL,
|
|
86613
|
-
status text NOT NULL DEFAULT 'open',
|
|
86614
|
-
first_seen_at timestamptz NOT NULL,
|
|
86615
|
-
last_seen_at timestamptz NOT NULL,
|
|
86616
|
-
occurrence_count integer NOT NULL DEFAULT 1,
|
|
86617
|
-
matched_fields text[],
|
|
86618
|
-
created_at timestamptz NOT NULL DEFAULT now(),
|
|
86619
|
-
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
86620
|
-
regressed_at timestamptz,
|
|
86621
|
-
spike_detected_at timestamptz,
|
|
86622
|
-
frequency_occurrences_1m integer,
|
|
86623
|
-
frequency_occurrences_5m integer,
|
|
86624
|
-
frequency_occurrences_1h integer,
|
|
86625
|
-
frequency_occurrences_24h integer,
|
|
86626
|
-
frequency_baseline_1h_per_5m double precision,
|
|
86627
|
-
frequency_spike_ratio_5m_to_1h double precision,
|
|
86628
|
-
frequency_has_sufficient_baseline boolean,
|
|
86629
|
-
frequency_is_spiking boolean,
|
|
86630
|
-
frequency_snapshot_at timestamptz,
|
|
86631
|
-
latest_deployment_id uuid REFERENCES deployments(id) ON DELETE SET NULL,
|
|
86632
|
-
bundle_generation_number integer NOT NULL DEFAULT 0,
|
|
86633
|
-
bundle_created_at timestamptz,
|
|
86634
|
-
bundle_updated_at timestamptz,
|
|
86635
|
-
bundle_source_event_id uuid,
|
|
86636
|
-
bundle_source_occurred_at timestamptz,
|
|
86637
|
-
bundle_trigger text,
|
|
86638
|
-
bundle_failure_reason text,
|
|
86639
|
-
resolved_at timestamptz,
|
|
86640
|
-
resolved_by_member_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
86641
|
-
UNIQUE (project_id, environment, service_id, fingerprint)
|
|
86642
|
-
)
|
|
86643
|
-
`,
|
|
86644
|
-
`
|
|
86645
|
-
CREATE TABLE processed_events (
|
|
86646
|
-
event_id uuid PRIMARY KEY,
|
|
86647
|
-
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
86648
|
-
event_type text NOT NULL,
|
|
86649
|
-
fingerprint text NOT NULL,
|
|
86650
|
-
normalized_message text NOT NULL,
|
|
86651
|
-
processed_at timestamptz NOT NULL DEFAULT now()
|
|
86652
|
-
)
|
|
86653
|
-
`,
|
|
86654
|
-
`
|
|
86655
|
-
CREATE TABLE improvement_opportunities (
|
|
86656
|
-
id uuid PRIMARY KEY,
|
|
86657
|
-
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
86658
|
-
service_id uuid REFERENCES services(id) ON DELETE SET NULL,
|
|
86659
|
-
service_name text NOT NULL,
|
|
86660
|
-
environment text NOT NULL DEFAULT 'production',
|
|
86661
|
-
kind text NOT NULL,
|
|
86662
|
-
status text NOT NULL DEFAULT 'open',
|
|
86663
|
-
severity text NOT NULL,
|
|
86664
|
-
confidence numeric NOT NULL,
|
|
86665
|
-
fingerprint text NOT NULL,
|
|
86666
|
-
title text NOT NULL,
|
|
86667
|
-
summary text NOT NULL,
|
|
86668
|
-
occurrence_count integer NOT NULL DEFAULT 1,
|
|
86669
|
-
evidence jsonb NOT NULL,
|
|
86670
|
-
first_detected_at timestamptz NOT NULL,
|
|
86671
|
-
last_detected_at timestamptz NOT NULL,
|
|
86672
|
-
last_source_event_id uuid,
|
|
86673
|
-
related_incident_ids uuid[] NOT NULL DEFAULT '{}',
|
|
86674
|
-
bundle_generation_number integer NOT NULL DEFAULT 0,
|
|
86675
|
-
bundle_created_at timestamptz,
|
|
86676
|
-
bundle_updated_at timestamptz,
|
|
86677
|
-
bundle_source_event_id uuid,
|
|
86678
|
-
bundle_failure_reason text,
|
|
86679
|
-
resolved_at timestamptz,
|
|
86680
|
-
resolved_by_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
86681
|
-
snoozed_until timestamptz,
|
|
86682
|
-
created_at timestamptz NOT NULL DEFAULT now(),
|
|
86683
|
-
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
86684
|
-
UNIQUE (project_id, fingerprint)
|
|
86685
|
-
)
|
|
86686
|
-
`,
|
|
86687
|
-
`
|
|
86688
|
-
CREATE INDEX improvement_opportunities_project_status_detected_idx
|
|
86689
|
-
ON improvement_opportunities (project_id, status, last_detected_at DESC)
|
|
86690
|
-
`,
|
|
86691
|
-
`
|
|
86692
|
-
CREATE INDEX improvement_opportunities_project_kind_detected_idx
|
|
86693
|
-
ON improvement_opportunities (project_id, kind, last_detected_at DESC)
|
|
86694
|
-
`,
|
|
86695
|
-
`
|
|
86696
|
-
CREATE INDEX improvement_opportunities_project_service_env_idx
|
|
86697
|
-
ON improvement_opportunities (project_id, service_id, environment)
|
|
86698
|
-
`,
|
|
86699
|
-
`
|
|
86700
|
-
CREATE TABLE improvement_opportunity_events (
|
|
86701
|
-
improvement_opportunity_id uuid NOT NULL REFERENCES improvement_opportunities(id) ON DELETE CASCADE,
|
|
86702
|
-
event_id uuid NOT NULL,
|
|
86703
|
-
event_type text NOT NULL,
|
|
86704
|
-
occurred_at timestamptz NOT NULL,
|
|
86705
|
-
PRIMARY KEY (improvement_opportunity_id, event_id)
|
|
86706
|
-
)
|
|
86707
|
-
`,
|
|
86708
|
-
`
|
|
86709
|
-
CREATE INDEX improvement_opportunity_events_detected_idx
|
|
86710
|
-
ON improvement_opportunity_events (improvement_opportunity_id, occurred_at DESC, event_id DESC)
|
|
86711
|
-
`,
|
|
86712
|
-
`
|
|
86713
|
-
CREATE TABLE bundle_generations (
|
|
86714
|
-
id uuid PRIMARY KEY,
|
|
86715
|
-
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
86716
|
-
incident_id uuid REFERENCES incidents(id) ON DELETE CASCADE,
|
|
86717
|
-
improvement_opportunity_id uuid REFERENCES improvement_opportunities(id) ON DELETE CASCADE,
|
|
86718
|
-
bundle_type text NOT NULL,
|
|
86719
|
-
generation_number integer NOT NULL,
|
|
86720
|
-
source_event_id uuid NOT NULL,
|
|
86721
|
-
source_occurred_at timestamptz NOT NULL,
|
|
86722
|
-
trigger text NOT NULL,
|
|
86723
|
-
created_at timestamptz NOT NULL,
|
|
86724
|
-
updated_at timestamptz NOT NULL,
|
|
86725
|
-
CHECK (
|
|
86726
|
-
(incident_id IS NOT NULL AND improvement_opportunity_id IS NULL AND bundle_type = 'failure')
|
|
86727
|
-
OR (incident_id IS NULL AND improvement_opportunity_id IS NOT NULL AND bundle_type = 'improvement')
|
|
86728
|
-
)
|
|
86729
|
-
)
|
|
86730
|
-
`,
|
|
86731
|
-
`
|
|
86732
|
-
CREATE UNIQUE INDEX bundle_generations_incident_source_idx
|
|
86733
|
-
ON bundle_generations (incident_id, source_event_id)
|
|
86734
|
-
WHERE incident_id IS NOT NULL
|
|
86735
|
-
`,
|
|
86736
|
-
`
|
|
86737
|
-
CREATE UNIQUE INDEX bundle_generations_improvement_source_idx
|
|
86738
|
-
ON bundle_generations (improvement_opportunity_id, source_event_id)
|
|
86739
|
-
WHERE improvement_opportunity_id IS NOT NULL
|
|
86740
|
-
`,
|
|
86741
|
-
`
|
|
86742
|
-
CREATE INDEX bundle_generations_project_created_idx
|
|
86743
|
-
ON bundle_generations (project_id, created_at DESC, bundle_type)
|
|
86744
|
-
`,
|
|
86745
|
-
`
|
|
86746
|
-
CREATE INDEX bundle_generations_incident_generation_idx
|
|
86747
|
-
ON bundle_generations (incident_id, generation_number DESC)
|
|
86748
|
-
`,
|
|
86749
|
-
`
|
|
86750
|
-
CREATE INDEX bundle_generations_improvement_generation_idx
|
|
86751
|
-
ON bundle_generations (improvement_opportunity_id, generation_number DESC)
|
|
86752
|
-
WHERE improvement_opportunity_id IS NOT NULL
|
|
86753
|
-
`,
|
|
86754
|
-
`
|
|
86755
|
-
CREATE TABLE incident_events (
|
|
86756
|
-
incident_id uuid NOT NULL REFERENCES incidents(id) ON DELETE CASCADE,
|
|
86757
|
-
event_id uuid NOT NULL,
|
|
86758
|
-
event_type text NOT NULL,
|
|
86759
|
-
event_class text NOT NULL DEFAULT 'context_signal',
|
|
86760
|
-
occurred_at timestamptz NOT NULL,
|
|
86761
|
-
is_sampled boolean NOT NULL DEFAULT false,
|
|
86762
|
-
level text,
|
|
86763
|
-
retain_first boolean NOT NULL DEFAULT false,
|
|
86764
|
-
retain_latest boolean NOT NULL DEFAULT false,
|
|
86765
|
-
retain_after_deploy boolean NOT NULL DEFAULT false,
|
|
86766
|
-
retain_highest_severity boolean NOT NULL DEFAULT false,
|
|
86767
|
-
retain_deploy_metadata boolean NOT NULL DEFAULT false,
|
|
86768
|
-
severity_rank integer NOT NULL DEFAULT 0,
|
|
86769
|
-
PRIMARY KEY (incident_id, event_id)
|
|
86770
|
-
)
|
|
86771
|
-
`,
|
|
86772
|
-
`
|
|
86773
|
-
CREATE INDEX incident_events_incident_occurred_event_idx
|
|
86774
|
-
ON incident_events (incident_id, occurred_at DESC, event_id DESC)
|
|
86775
|
-
`,
|
|
86776
|
-
`
|
|
86777
|
-
CREATE INDEX incident_events_incident_level_occurred_event_idx
|
|
86778
|
-
ON incident_events (incident_id, level, occurred_at DESC, event_id DESC)
|
|
86779
|
-
`,
|
|
86780
|
-
`
|
|
86781
|
-
CREATE INDEX incident_events_incident_sampled_idx
|
|
86782
|
-
ON incident_events (incident_id, is_sampled, occurred_at ASC, event_id ASC)
|
|
86783
|
-
`,
|
|
86998
|
+
...STORAGE_BOOTSTRAP_INCIDENT_STATEMENTS,
|
|
86784
86999
|
`
|
|
86785
87000
|
CREATE TABLE weekly_report_channels (
|
|
86786
87001
|
id uuid PRIMARY KEY,
|
|
@@ -89369,7 +89584,12 @@ var LATE_STORAGE_SCHEMA_MIGRATIONS = [
|
|
|
89369
89584
|
// ../../packages/storage/src/schema-migrations-catalog.ts
|
|
89370
89585
|
var STORAGE_SCHEMA_MIGRATIONS = [
|
|
89371
89586
|
...EARLY_STORAGE_SCHEMA_MIGRATIONS,
|
|
89372
|
-
...LATE_STORAGE_SCHEMA_MIGRATIONS
|
|
89587
|
+
...LATE_STORAGE_SCHEMA_MIGRATIONS,
|
|
89588
|
+
defineStorageSchemaMigration({
|
|
89589
|
+
id: "202609160001_add_browser_resource_routes",
|
|
89590
|
+
description: "Retain sanitized browser resource routes independently of raw event sampling.",
|
|
89591
|
+
statements: ["ALTER TABLE incident_events ADD COLUMN IF NOT EXISTS resource_route text"]
|
|
89592
|
+
})
|
|
89373
89593
|
];
|
|
89374
89594
|
|
|
89375
89595
|
// ../../packages/storage/src/schema-migrations.ts
|
|
@@ -93745,6 +93965,27 @@ var import_node_crypto10 = require("node:crypto");
|
|
|
93745
93965
|
var import_promises10 = require("node:fs/promises");
|
|
93746
93966
|
var import_node_path11 = require("node:path");
|
|
93747
93967
|
|
|
93968
|
+
// ../../packages/bundle-engine/src/browser-resource-context.ts
|
|
93969
|
+
function buildBrowserResourceContext(browserEvent, incident, events2) {
|
|
93970
|
+
const resource = describeBrowserResource(browserEvent);
|
|
93971
|
+
if (resource === null) return void 0;
|
|
93972
|
+
const routes = [];
|
|
93973
|
+
for (const event of events2) {
|
|
93974
|
+
if (event.event_type !== "frontend_exception" || event.service.name !== incident.service_name || event.service.environment !== incident.environment)
|
|
93975
|
+
continue;
|
|
93976
|
+
const candidate = describeBrowserResource(event.payload.browser_event);
|
|
93977
|
+
if (candidate !== null && candidate.host === resource.host && candidate.path === resource.path && candidate.type === resource.type) {
|
|
93978
|
+
routes.push(event.payload.route ?? null);
|
|
93979
|
+
}
|
|
93980
|
+
}
|
|
93981
|
+
return {
|
|
93982
|
+
version: 1,
|
|
93983
|
+
...resource,
|
|
93984
|
+
diagnosis: browserResourceDiagnosis(resource),
|
|
93985
|
+
routes: incident.resource_routes ?? summarizeResourceRoutes(routes, incident.occurrence_count)
|
|
93986
|
+
};
|
|
93987
|
+
}
|
|
93988
|
+
|
|
93748
93989
|
// ../../packages/bundle-engine/src/deployment-context.ts
|
|
93749
93990
|
function selectScopedDeployments(input3) {
|
|
93750
93991
|
const cutoff = Date.parse(input3.occurredAt);
|
|
@@ -93830,9 +94071,9 @@ function stableJson2(value) {
|
|
|
93830
94071
|
if (Array.isArray(value)) {
|
|
93831
94072
|
return `[${value.map((entry) => stableJson2(entry)).join(",")}]`;
|
|
93832
94073
|
}
|
|
93833
|
-
const
|
|
93834
|
-
const keys2 = Object.keys(
|
|
93835
|
-
return `{${keys2.map((key) => `${JSON.stringify(key)}:${stableJson2(
|
|
94074
|
+
const record2 = value;
|
|
94075
|
+
const keys2 = Object.keys(record2).sort();
|
|
94076
|
+
return `{${keys2.map((key) => `${JSON.stringify(key)}:${stableJson2(record2[key])}`).join(",")}}`;
|
|
93836
94077
|
}
|
|
93837
94078
|
function buildFrontendBreadcrumbKey(input3) {
|
|
93838
94079
|
return `${input3.breadcrumb_type}:${input3.ts}:${input3.route ?? ""}:${stableJson2(input3.data)}`;
|
|
@@ -94206,10 +94447,11 @@ function buildSummaryGuidance(input3) {
|
|
|
94206
94447
|
}
|
|
94207
94448
|
if (input3.opaqueBrowserError) {
|
|
94208
94449
|
if (input3.browserEvent?.kind === "resource_error") {
|
|
94450
|
+
const resource = describeBrowserResource(input3.browserEvent);
|
|
94209
94451
|
return {
|
|
94210
|
-
likely_cause:
|
|
94452
|
+
likely_cause: browserResourceDiagnosis(resource),
|
|
94211
94453
|
confidence: 0.35,
|
|
94212
|
-
recommended_action: "
|
|
94454
|
+
recommended_action: "Check the affected resource and routes, browser network failures, CSP and provider availability." + (resource?.optional_candidate === true ? " If the dependency is optional for your app, review a resource-scoped noise rule." : " Verify whether application functionality is affected.")
|
|
94213
94455
|
};
|
|
94214
94456
|
}
|
|
94215
94457
|
return {
|
|
@@ -94483,8 +94725,10 @@ function buildBundle(input3) {
|
|
|
94483
94725
|
errorContext,
|
|
94484
94726
|
requestContext
|
|
94485
94727
|
);
|
|
94486
|
-
const
|
|
94728
|
+
const browserEventCandidate = getPrimaryBrowserExceptionEvent(sourceEnvelopes, primarySignalEnvelope);
|
|
94729
|
+
const browserEvent = browserEventCandidate?.kind === "resource_error" && primarySignalEnvelope !== null && !isFrontendExceptionEnvelope(primarySignalEnvelope) ? null : browserEventCandidate;
|
|
94487
94730
|
const opaqueBrowserError = isOpaqueBrowserError(errorContext, browserEvent);
|
|
94731
|
+
const resourceContext = buildBrowserResourceContext(browserEvent, input3.incident, sourceEnvelopes);
|
|
94488
94732
|
const primarySignalType = primarySignalEnvelope !== null ? mapSignalType(primarySignalEnvelope.event_type) : inferSignalTypeFromSourceEventTypes(sourceEventTypes);
|
|
94489
94733
|
const primarySourceEvent = errorContext?.name ?? sourceEventTypes[0] ?? "backend_exception";
|
|
94490
94734
|
const firstSeenAt = new Date(input3.incident.first_seen_at).toISOString();
|
|
@@ -94558,6 +94802,7 @@ function buildBundle(input3) {
|
|
|
94558
94802
|
regression_suspected: input3.job.trigger === "regression_reopen"
|
|
94559
94803
|
},
|
|
94560
94804
|
context: {
|
|
94805
|
+
...resourceContext === void 0 ? {} : { resource_failure: resourceContext },
|
|
94561
94806
|
error: errorContext,
|
|
94562
94807
|
request: requestContext,
|
|
94563
94808
|
response: responseContext,
|
|
@@ -94621,8 +94866,8 @@ function stableStringify(value) {
|
|
|
94621
94866
|
function shellQuote(value) {
|
|
94622
94867
|
return `'${value.replaceAll("'", `'\\''`)}'`;
|
|
94623
94868
|
}
|
|
94624
|
-
function sortRecordEntries(
|
|
94625
|
-
return Object.entries(
|
|
94869
|
+
function sortRecordEntries(record2) {
|
|
94870
|
+
return Object.entries(record2).sort(([left], [right]) => left.localeCompare(right));
|
|
94626
94871
|
}
|
|
94627
94872
|
var REPLAY_HEADER_PRIORITY = [
|
|
94628
94873
|
"authorization",
|
|
@@ -94927,6 +95172,159 @@ function buildReproduction(bundle) {
|
|
|
94927
95172
|
};
|
|
94928
95173
|
}
|
|
94929
95174
|
|
|
95175
|
+
// src/local-processing-state.ts
|
|
95176
|
+
var EVENT_TYPE_SET = new Set(EventTypeValues);
|
|
95177
|
+
function isEventType(value) {
|
|
95178
|
+
return typeof value === "string" && EVENT_TYPE_SET.has(value);
|
|
95179
|
+
}
|
|
95180
|
+
function parseIncidentState(candidate) {
|
|
95181
|
+
if (!isRecord(candidate)) {
|
|
95182
|
+
return null;
|
|
95183
|
+
}
|
|
95184
|
+
if (candidate["source"] !== "local" || candidate["status"] !== "open" && candidate["status"] !== "resolved") {
|
|
95185
|
+
return null;
|
|
95186
|
+
}
|
|
95187
|
+
const sourceEvents = candidate["source_events"];
|
|
95188
|
+
if (!Array.isArray(sourceEvents)) {
|
|
95189
|
+
return null;
|
|
95190
|
+
}
|
|
95191
|
+
const validatedSourceEvents = [];
|
|
95192
|
+
for (const sourceEvent of sourceEvents) {
|
|
95193
|
+
const validated = validateEvent(sourceEvent);
|
|
95194
|
+
if (!validated.success) {
|
|
95195
|
+
return null;
|
|
95196
|
+
}
|
|
95197
|
+
validatedSourceEvents.push(validated.data);
|
|
95198
|
+
}
|
|
95199
|
+
const matchedFields = candidate["matched_fields"];
|
|
95200
|
+
const sourceEventTypes = candidate["source_event_types"];
|
|
95201
|
+
if (!Array.isArray(matchedFields) || !matchedFields.every((value) => typeof value === "string")) {
|
|
95202
|
+
return null;
|
|
95203
|
+
}
|
|
95204
|
+
if (!Array.isArray(sourceEventTypes) || !sourceEventTypes.every(isEventType)) {
|
|
95205
|
+
return null;
|
|
95206
|
+
}
|
|
95207
|
+
const severity = candidate["severity"];
|
|
95208
|
+
if (severity !== "low" && severity !== "medium" && severity !== "high" && severity !== "critical") {
|
|
95209
|
+
return null;
|
|
95210
|
+
}
|
|
95211
|
+
const status = candidate["status"];
|
|
95212
|
+
if (status !== "open" && status !== "resolved") {
|
|
95213
|
+
return null;
|
|
95214
|
+
}
|
|
95215
|
+
const requiredStringKeys = [
|
|
95216
|
+
"incident_id",
|
|
95217
|
+
"project_id",
|
|
95218
|
+
"service_id",
|
|
95219
|
+
"service_name",
|
|
95220
|
+
"environment",
|
|
95221
|
+
"fingerprint",
|
|
95222
|
+
"fingerprint_version",
|
|
95223
|
+
"title",
|
|
95224
|
+
"first_seen_at",
|
|
95225
|
+
"last_seen_at",
|
|
95226
|
+
"source_event_id",
|
|
95227
|
+
"source_occurred_at",
|
|
95228
|
+
"bundle_path",
|
|
95229
|
+
"reproduction_path"
|
|
95230
|
+
];
|
|
95231
|
+
for (const key of requiredStringKeys) {
|
|
95232
|
+
if (typeof candidate[key] !== "string") {
|
|
95233
|
+
return null;
|
|
95234
|
+
}
|
|
95235
|
+
}
|
|
95236
|
+
if (typeof candidate["occurrence_count"] !== "number" || typeof candidate["generation_number"] !== "number") {
|
|
95237
|
+
return null;
|
|
95238
|
+
}
|
|
95239
|
+
const serviceRuntime = candidate["service_runtime"];
|
|
95240
|
+
const serviceFramework = candidate["service_framework"];
|
|
95241
|
+
if (serviceRuntime !== null && typeof serviceRuntime !== "string") {
|
|
95242
|
+
return null;
|
|
95243
|
+
}
|
|
95244
|
+
if (serviceFramework !== null && typeof serviceFramework !== "string") {
|
|
95245
|
+
return null;
|
|
95246
|
+
}
|
|
95247
|
+
const incidentId = candidate["incident_id"];
|
|
95248
|
+
const projectId = candidate["project_id"];
|
|
95249
|
+
const serviceId = candidate["service_id"];
|
|
95250
|
+
const serviceName = candidate["service_name"];
|
|
95251
|
+
const environment = candidate["environment"];
|
|
95252
|
+
const incidentFingerprint = candidate["fingerprint"];
|
|
95253
|
+
const fingerprintVersion2 = candidate["fingerprint_version"];
|
|
95254
|
+
const title = candidate["title"];
|
|
95255
|
+
const firstSeenAt = candidate["first_seen_at"];
|
|
95256
|
+
const lastSeenAt = candidate["last_seen_at"];
|
|
95257
|
+
const occurrenceCount = candidate["occurrence_count"];
|
|
95258
|
+
const sourceEventId = candidate["source_event_id"];
|
|
95259
|
+
const sourceOccurredAt = candidate["source_occurred_at"];
|
|
95260
|
+
const bundlePath = candidate["bundle_path"];
|
|
95261
|
+
const reproductionPath = candidate["reproduction_path"];
|
|
95262
|
+
const generationNumber = candidate["generation_number"];
|
|
95263
|
+
const normalizedSourceEventTypes = [...sourceEventTypes].sort();
|
|
95264
|
+
return {
|
|
95265
|
+
incident_id: incidentId,
|
|
95266
|
+
source: "local",
|
|
95267
|
+
project_id: projectId,
|
|
95268
|
+
service_id: serviceId,
|
|
95269
|
+
service_name: serviceName,
|
|
95270
|
+
service_runtime: serviceRuntime,
|
|
95271
|
+
service_framework: serviceFramework,
|
|
95272
|
+
environment,
|
|
95273
|
+
fingerprint: incidentFingerprint,
|
|
95274
|
+
fingerprint_version: fingerprintVersion2,
|
|
95275
|
+
title,
|
|
95276
|
+
severity,
|
|
95277
|
+
status,
|
|
95278
|
+
first_seen_at: firstSeenAt,
|
|
95279
|
+
last_seen_at: lastSeenAt,
|
|
95280
|
+
occurrence_count: occurrenceCount,
|
|
95281
|
+
source_event_id: sourceEventId,
|
|
95282
|
+
source_occurred_at: sourceOccurredAt,
|
|
95283
|
+
source_event_types: normalizedSourceEventTypes,
|
|
95284
|
+
matched_fields: [...matchedFields].sort(),
|
|
95285
|
+
bundle_path: bundlePath,
|
|
95286
|
+
reproduction_path: reproductionPath,
|
|
95287
|
+
generation_number: generationNumber,
|
|
95288
|
+
source_events: validatedSourceEvents.sort(compareEventEnvelopes)
|
|
95289
|
+
};
|
|
95290
|
+
}
|
|
95291
|
+
function parseState(rawState) {
|
|
95292
|
+
const parsed = JSON.parse(rawState);
|
|
95293
|
+
if (!isRecord(parsed) || parsed["version"] !== 1) {
|
|
95294
|
+
return null;
|
|
95295
|
+
}
|
|
95296
|
+
const lastProcessedEventFile = parsed["last_processed_event_file"];
|
|
95297
|
+
if (lastProcessedEventFile !== null && typeof lastProcessedEventFile !== "string") {
|
|
95298
|
+
return null;
|
|
95299
|
+
}
|
|
95300
|
+
const incidents = parsed["incidents"];
|
|
95301
|
+
if (!isRecord(incidents)) {
|
|
95302
|
+
return null;
|
|
95303
|
+
}
|
|
95304
|
+
const parsedIncidents = {};
|
|
95305
|
+
for (const [incidentId, incidentValue] of Object.entries(incidents).sort(
|
|
95306
|
+
([left], [right]) => left.localeCompare(right)
|
|
95307
|
+
)) {
|
|
95308
|
+
const incident = parseIncidentState(incidentValue);
|
|
95309
|
+
if (incident === null || incident.incident_id !== incidentId) {
|
|
95310
|
+
return null;
|
|
95311
|
+
}
|
|
95312
|
+
parsedIncidents[incidentId] = incident;
|
|
95313
|
+
}
|
|
95314
|
+
return {
|
|
95315
|
+
version: 1,
|
|
95316
|
+
last_processed_event_file: lastProcessedEventFile,
|
|
95317
|
+
incidents: parsedIncidents
|
|
95318
|
+
};
|
|
95319
|
+
}
|
|
95320
|
+
function compareEventEnvelopes(left, right) {
|
|
95321
|
+
const occurredAtComparison = left.occurred_at.localeCompare(right.occurred_at);
|
|
95322
|
+
if (occurredAtComparison !== 0) {
|
|
95323
|
+
return occurredAtComparison;
|
|
95324
|
+
}
|
|
95325
|
+
return left.event_id.localeCompare(right.event_id);
|
|
95326
|
+
}
|
|
95327
|
+
|
|
94930
95328
|
// src/process-command.ts
|
|
94931
95329
|
var LOCAL_EVENTS_DIRECTORY_PATH2 = ".debugbundle/local/events";
|
|
94932
95330
|
var LOCAL_STATE_FILE_PATH = ".debugbundle/local/state.json";
|
|
@@ -94937,10 +95335,6 @@ var CLI_SDK = {
|
|
|
94937
95335
|
name: "debugbundle-cli",
|
|
94938
95336
|
version: "0.1.0"
|
|
94939
95337
|
};
|
|
94940
|
-
var EVENT_TYPE_SET = new Set(EventTypeValues);
|
|
94941
|
-
function isEventType(value) {
|
|
94942
|
-
return typeof value === "string" && EVENT_TYPE_SET.has(value);
|
|
94943
|
-
}
|
|
94944
95338
|
function inferSeverity2(event, capturePreset, incidentKind = "immediate") {
|
|
94945
95339
|
if (incidentKind === "request_anomaly") {
|
|
94946
95340
|
return "medium";
|
|
@@ -94948,7 +95342,8 @@ function inferSeverity2(event, capturePreset, incidentKind = "immediate") {
|
|
|
94948
95342
|
if (event.event_type === "request_event") {
|
|
94949
95343
|
return classifyRequestStatus({ responseStatus: event.payload.response_status, capturePreset }) === "incident_signal" ? "high" : "low";
|
|
94950
95344
|
}
|
|
94951
|
-
if (event.event_type === "
|
|
95345
|
+
if (event.event_type === "frontend_exception") return inferFrontendExceptionSeverity(event);
|
|
95346
|
+
if (event.event_type === "backend_exception") {
|
|
94952
95347
|
return "high";
|
|
94953
95348
|
}
|
|
94954
95349
|
if (event.event_type === "error_suppressed") {
|
|
@@ -94968,13 +95363,6 @@ function severityRank(severity) {
|
|
|
94968
95363
|
return 1;
|
|
94969
95364
|
}
|
|
94970
95365
|
}
|
|
94971
|
-
function compareEventEnvelopes(left, right) {
|
|
94972
|
-
const occurredAtComparison = left.occurred_at.localeCompare(right.occurred_at);
|
|
94973
|
-
if (occurredAtComparison !== 0) {
|
|
94974
|
-
return occurredAtComparison;
|
|
94975
|
-
}
|
|
94976
|
-
return left.event_id.localeCompare(right.event_id);
|
|
94977
|
-
}
|
|
94978
95366
|
function classifyEnvelope(envelope, capturePreset) {
|
|
94979
95367
|
return classifyEvent(
|
|
94980
95368
|
envelope.event_type,
|
|
@@ -95066,9 +95454,9 @@ function stableJson3(value) {
|
|
|
95066
95454
|
if (Array.isArray(value)) {
|
|
95067
95455
|
return `[${value.map((entry) => stableJson3(entry)).join(",")}]`;
|
|
95068
95456
|
}
|
|
95069
|
-
const
|
|
95070
|
-
const keys2 = Object.keys(
|
|
95071
|
-
return `{${keys2.map((key) => `${JSON.stringify(key)}:${stableJson3(
|
|
95457
|
+
const record2 = value;
|
|
95458
|
+
const keys2 = Object.keys(record2).sort();
|
|
95459
|
+
return `{${keys2.map((key) => `${JSON.stringify(key)}:${stableJson3(record2[key])}`).join(",")}}`;
|
|
95072
95460
|
}
|
|
95073
95461
|
function buildRequestAnomalyFingerprint(input3) {
|
|
95074
95462
|
return (0, import_node_crypto10.createHash)("sha256").update(
|
|
@@ -95221,144 +95609,6 @@ async function pathExists4(path, stat) {
|
|
|
95221
95609
|
throw error;
|
|
95222
95610
|
}
|
|
95223
95611
|
}
|
|
95224
|
-
function parseIncidentState(candidate) {
|
|
95225
|
-
if (!isRecord(candidate)) {
|
|
95226
|
-
return null;
|
|
95227
|
-
}
|
|
95228
|
-
if (candidate["source"] !== "local" || candidate["status"] !== "open" && candidate["status"] !== "resolved") {
|
|
95229
|
-
return null;
|
|
95230
|
-
}
|
|
95231
|
-
const sourceEvents = candidate["source_events"];
|
|
95232
|
-
if (!Array.isArray(sourceEvents)) {
|
|
95233
|
-
return null;
|
|
95234
|
-
}
|
|
95235
|
-
const validatedSourceEvents = [];
|
|
95236
|
-
for (const sourceEvent of sourceEvents) {
|
|
95237
|
-
const validated = validateEvent(sourceEvent);
|
|
95238
|
-
if (!validated.success) {
|
|
95239
|
-
return null;
|
|
95240
|
-
}
|
|
95241
|
-
validatedSourceEvents.push(validated.data);
|
|
95242
|
-
}
|
|
95243
|
-
const matchedFields = candidate["matched_fields"];
|
|
95244
|
-
const sourceEventTypes = candidate["source_event_types"];
|
|
95245
|
-
if (!Array.isArray(matchedFields) || !matchedFields.every((value) => typeof value === "string")) {
|
|
95246
|
-
return null;
|
|
95247
|
-
}
|
|
95248
|
-
if (!Array.isArray(sourceEventTypes) || !sourceEventTypes.every(isEventType)) {
|
|
95249
|
-
return null;
|
|
95250
|
-
}
|
|
95251
|
-
const severity = candidate["severity"];
|
|
95252
|
-
if (severity !== "low" && severity !== "medium" && severity !== "high" && severity !== "critical") {
|
|
95253
|
-
return null;
|
|
95254
|
-
}
|
|
95255
|
-
const status = candidate["status"];
|
|
95256
|
-
if (status !== "open" && status !== "resolved") {
|
|
95257
|
-
return null;
|
|
95258
|
-
}
|
|
95259
|
-
const requiredStringKeys = [
|
|
95260
|
-
"incident_id",
|
|
95261
|
-
"project_id",
|
|
95262
|
-
"service_id",
|
|
95263
|
-
"service_name",
|
|
95264
|
-
"environment",
|
|
95265
|
-
"fingerprint",
|
|
95266
|
-
"fingerprint_version",
|
|
95267
|
-
"title",
|
|
95268
|
-
"first_seen_at",
|
|
95269
|
-
"last_seen_at",
|
|
95270
|
-
"source_event_id",
|
|
95271
|
-
"source_occurred_at",
|
|
95272
|
-
"bundle_path",
|
|
95273
|
-
"reproduction_path"
|
|
95274
|
-
];
|
|
95275
|
-
for (const key of requiredStringKeys) {
|
|
95276
|
-
if (typeof candidate[key] !== "string") {
|
|
95277
|
-
return null;
|
|
95278
|
-
}
|
|
95279
|
-
}
|
|
95280
|
-
if (typeof candidate["occurrence_count"] !== "number" || typeof candidate["generation_number"] !== "number") {
|
|
95281
|
-
return null;
|
|
95282
|
-
}
|
|
95283
|
-
const serviceRuntime = candidate["service_runtime"];
|
|
95284
|
-
const serviceFramework = candidate["service_framework"];
|
|
95285
|
-
if (serviceRuntime !== null && typeof serviceRuntime !== "string") {
|
|
95286
|
-
return null;
|
|
95287
|
-
}
|
|
95288
|
-
if (serviceFramework !== null && typeof serviceFramework !== "string") {
|
|
95289
|
-
return null;
|
|
95290
|
-
}
|
|
95291
|
-
const incidentId = candidate["incident_id"];
|
|
95292
|
-
const projectId = candidate["project_id"];
|
|
95293
|
-
const serviceId = candidate["service_id"];
|
|
95294
|
-
const serviceName = candidate["service_name"];
|
|
95295
|
-
const environment = candidate["environment"];
|
|
95296
|
-
const incidentFingerprint = candidate["fingerprint"];
|
|
95297
|
-
const fingerprintVersion = candidate["fingerprint_version"];
|
|
95298
|
-
const title = candidate["title"];
|
|
95299
|
-
const firstSeenAt = candidate["first_seen_at"];
|
|
95300
|
-
const lastSeenAt = candidate["last_seen_at"];
|
|
95301
|
-
const occurrenceCount = candidate["occurrence_count"];
|
|
95302
|
-
const sourceEventId = candidate["source_event_id"];
|
|
95303
|
-
const sourceOccurredAt = candidate["source_occurred_at"];
|
|
95304
|
-
const bundlePath = candidate["bundle_path"];
|
|
95305
|
-
const reproductionPath = candidate["reproduction_path"];
|
|
95306
|
-
const generationNumber = candidate["generation_number"];
|
|
95307
|
-
const normalizedSourceEventTypes = [...sourceEventTypes].sort();
|
|
95308
|
-
return {
|
|
95309
|
-
incident_id: incidentId,
|
|
95310
|
-
source: "local",
|
|
95311
|
-
project_id: projectId,
|
|
95312
|
-
service_id: serviceId,
|
|
95313
|
-
service_name: serviceName,
|
|
95314
|
-
service_runtime: serviceRuntime,
|
|
95315
|
-
service_framework: serviceFramework,
|
|
95316
|
-
environment,
|
|
95317
|
-
fingerprint: incidentFingerprint,
|
|
95318
|
-
fingerprint_version: fingerprintVersion,
|
|
95319
|
-
title,
|
|
95320
|
-
severity,
|
|
95321
|
-
status,
|
|
95322
|
-
first_seen_at: firstSeenAt,
|
|
95323
|
-
last_seen_at: lastSeenAt,
|
|
95324
|
-
occurrence_count: occurrenceCount,
|
|
95325
|
-
source_event_id: sourceEventId,
|
|
95326
|
-
source_occurred_at: sourceOccurredAt,
|
|
95327
|
-
source_event_types: normalizedSourceEventTypes,
|
|
95328
|
-
matched_fields: [...matchedFields].sort(),
|
|
95329
|
-
bundle_path: bundlePath,
|
|
95330
|
-
reproduction_path: reproductionPath,
|
|
95331
|
-
generation_number: generationNumber,
|
|
95332
|
-
source_events: validatedSourceEvents.sort(compareEventEnvelopes)
|
|
95333
|
-
};
|
|
95334
|
-
}
|
|
95335
|
-
function parseState(rawState) {
|
|
95336
|
-
const parsed = JSON.parse(rawState);
|
|
95337
|
-
if (!isRecord(parsed) || parsed["version"] !== 1) {
|
|
95338
|
-
return null;
|
|
95339
|
-
}
|
|
95340
|
-
const lastProcessedEventFile = parsed["last_processed_event_file"];
|
|
95341
|
-
if (lastProcessedEventFile !== null && typeof lastProcessedEventFile !== "string") {
|
|
95342
|
-
return null;
|
|
95343
|
-
}
|
|
95344
|
-
const incidents = parsed["incidents"];
|
|
95345
|
-
if (!isRecord(incidents)) {
|
|
95346
|
-
return null;
|
|
95347
|
-
}
|
|
95348
|
-
const parsedIncidents = {};
|
|
95349
|
-
for (const [incidentId, incidentValue] of Object.entries(incidents).sort(([left], [right]) => left.localeCompare(right))) {
|
|
95350
|
-
const incident = parseIncidentState(incidentValue);
|
|
95351
|
-
if (incident === null || incident.incident_id !== incidentId) {
|
|
95352
|
-
return null;
|
|
95353
|
-
}
|
|
95354
|
-
parsedIncidents[incidentId] = incident;
|
|
95355
|
-
}
|
|
95356
|
-
return {
|
|
95357
|
-
version: 1,
|
|
95358
|
-
last_processed_event_file: lastProcessedEventFile,
|
|
95359
|
-
incidents: parsedIncidents
|
|
95360
|
-
};
|
|
95361
|
-
}
|
|
95362
95612
|
async function readState(statePath, readFile, stat) {
|
|
95363
95613
|
if (!await pathExists4(statePath, stat)) {
|
|
95364
95614
|
return null;
|
|
@@ -95492,7 +95742,7 @@ async function processCommand(input3, dependencies = {}) {
|
|
|
95492
95742
|
mergedIncidentIds: /* @__PURE__ */ new Set([incidentId]),
|
|
95493
95743
|
signalEventTypes: /* @__PURE__ */ new Set(),
|
|
95494
95744
|
traceIds: /* @__PURE__ */ new Set(),
|
|
95495
|
-
title: normalizedEvent.normalized_message,
|
|
95745
|
+
title: normalizedEvent.incident_title ?? normalizedEvent.normalized_message,
|
|
95496
95746
|
kind: "immediate",
|
|
95497
95747
|
severity: inferSeverity2(event, capturePreset)
|
|
95498
95748
|
};
|
|
@@ -95502,7 +95752,7 @@ async function processCommand(input3, dependencies = {}) {
|
|
|
95502
95752
|
aggregate.newEvents.push(event);
|
|
95503
95753
|
aggregate.signalEventTypes.add(event.event_type);
|
|
95504
95754
|
const traceId = getTraceId(event);
|
|
95505
|
-
if (traceId !== null) {
|
|
95755
|
+
if (traceId !== null && normalizedEvent.resource_type === void 0) {
|
|
95506
95756
|
aggregate.traceIds.add(traceId);
|
|
95507
95757
|
const traceCorrelationGroup = traceCorrelationGroups.get(traceId) ?? {
|
|
95508
95758
|
incidentIds: /* @__PURE__ */ new Set(),
|
|
@@ -95594,7 +95844,7 @@ async function processCommand(input3, dependencies = {}) {
|
|
|
95594
95844
|
service_framework: latestSignalEvent.service.framework ?? existing?.service_framework ?? null,
|
|
95595
95845
|
environment: aggregate.environment,
|
|
95596
95846
|
fingerprint: aggregate.fingerprint,
|
|
95597
|
-
fingerprint_version: FINGERPRINT_VERSION,
|
|
95847
|
+
fingerprint_version: aggregate.kind === "request_anomaly" ? FINGERPRINT_VERSION : fingerprintVersion(normalizeEvent(latestSignalEvent)),
|
|
95598
95848
|
title: aggregate.title,
|
|
95599
95849
|
severity,
|
|
95600
95850
|
status: existingIncidents.some((incidentState) => incidentState.status === "resolved") ? "open" : existing?.status ?? "open",
|
|
@@ -107980,7 +108230,7 @@ async function handleCaptureRuleCommand2(parsedArgv, dependencies) {
|
|
|
107980
108230
|
// package.json
|
|
107981
108231
|
var package_default = {
|
|
107982
108232
|
name: "@debugbundle/cli",
|
|
107983
|
-
version: "1.
|
|
108233
|
+
version: "1.9.1",
|
|
107984
108234
|
private: false,
|
|
107985
108235
|
description: "Command-line interface for DebugBundle",
|
|
107986
108236
|
license: "Apache-2.0",
|