@debugbundle/mcp 1.1.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.cjs +374 -47
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/main.cjs
CHANGED
|
@@ -15094,7 +15094,7 @@ var ProjectMetricsSchema = external_exports.object({
|
|
|
15094
15094
|
monthly_raw_ingested_events: external_exports.number().int().nonnegative(),
|
|
15095
15095
|
retained_bundles: external_exports.number().int().nonnegative(),
|
|
15096
15096
|
monthly_alert_deliveries: external_exports.number().int().nonnegative()
|
|
15097
|
-
})
|
|
15097
|
+
});
|
|
15098
15098
|
var ProjectRecordSchema = external_exports.object({
|
|
15099
15099
|
project_id: external_exports.string(),
|
|
15100
15100
|
organization_id: external_exports.string(),
|
|
@@ -15111,13 +15111,13 @@ var ProjectRecordSchema = external_exports.object({
|
|
|
15111
15111
|
metrics: ProjectMetricsSchema,
|
|
15112
15112
|
created_at: external_exports.string(),
|
|
15113
15113
|
updated_at: external_exports.string()
|
|
15114
|
-
})
|
|
15114
|
+
});
|
|
15115
15115
|
var ProjectListResponseSchema = external_exports.object({
|
|
15116
15116
|
projects: external_exports.array(ProjectRecordSchema)
|
|
15117
|
-
})
|
|
15117
|
+
});
|
|
15118
15118
|
var ProjectCreateResponseSchema = external_exports.object({
|
|
15119
15119
|
project: ProjectRecordSchema
|
|
15120
|
-
})
|
|
15120
|
+
});
|
|
15121
15121
|
var DeletedProjectRecordSchema = external_exports.object({
|
|
15122
15122
|
project_id: external_exports.string(),
|
|
15123
15123
|
organization_id: external_exports.string(),
|
|
@@ -15133,10 +15133,10 @@ var DeletedProjectRecordSchema = external_exports.object({
|
|
|
15133
15133
|
organization_plan: external_exports.enum(["free", "solo", "team"]),
|
|
15134
15134
|
created_at: external_exports.string(),
|
|
15135
15135
|
updated_at: external_exports.string()
|
|
15136
|
-
})
|
|
15136
|
+
});
|
|
15137
15137
|
var ProjectDeleteResponseSchema = external_exports.object({
|
|
15138
15138
|
project: DeletedProjectRecordSchema
|
|
15139
|
-
})
|
|
15139
|
+
});
|
|
15140
15140
|
var ApiErrorResponseSchema4 = external_exports.object({
|
|
15141
15141
|
error: external_exports.string()
|
|
15142
15142
|
}).strict();
|
|
@@ -16501,25 +16501,74 @@ var CaptureProbeEventsSchema = external_exports.enum(CaptureProbeEventsValues);
|
|
|
16501
16501
|
var RequestSignalClassificationValues = ["incident_signal", "context_signal"];
|
|
16502
16502
|
var RequestSignalClassificationSchema = external_exports.enum(RequestSignalClassificationValues);
|
|
16503
16503
|
var RECOMMENDED_IMMEDIATE_CLIENT_ERROR_STATUSES = [401, 403, 409, 422];
|
|
16504
|
+
var HTTP_METHOD_VALUES = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
16504
16505
|
var ImmediateClientErrorStatusSchema = external_exports.number().int().min(400).max(499);
|
|
16506
|
+
var HttpMethodSchema = external_exports.enum(HTTP_METHOD_VALUES);
|
|
16505
16507
|
function normalizeImmediateClientErrorStatuses(statuses) {
|
|
16506
16508
|
return Array.from(new Set(statuses)).sort((left, right) => left - right);
|
|
16507
16509
|
}
|
|
16508
16510
|
var ImmediateClientErrorStatusesSchema = external_exports.array(ImmediateClientErrorStatusSchema).max(12).transform((statuses) => normalizeImmediateClientErrorStatuses(statuses));
|
|
16511
|
+
function normalizePathPattern(value) {
|
|
16512
|
+
return value.trim().replace(/\/{2,}/g, "/");
|
|
16513
|
+
}
|
|
16514
|
+
function isValidPathPattern(value) {
|
|
16515
|
+
const normalized = normalizePathPattern(value);
|
|
16516
|
+
if (!normalized.startsWith("/") || normalized.includes("?") || normalized.includes("#")) {
|
|
16517
|
+
return false;
|
|
16518
|
+
}
|
|
16519
|
+
const wildcardIndex = normalized.indexOf("*");
|
|
16520
|
+
return wildcardIndex === -1 || wildcardIndex === normalized.length - 1;
|
|
16521
|
+
}
|
|
16522
|
+
function normalizeHttpMethods(methods) {
|
|
16523
|
+
if (methods === void 0 || methods.length === 0) {
|
|
16524
|
+
return [];
|
|
16525
|
+
}
|
|
16526
|
+
const normalized = methods.map((method) => method.toUpperCase()).filter(
|
|
16527
|
+
(method) => HTTP_METHOD_VALUES.includes(method)
|
|
16528
|
+
);
|
|
16529
|
+
return Array.from(new Set(normalized)).sort();
|
|
16530
|
+
}
|
|
16531
|
+
function normalizeImmediateClientErrorPathRules(rules) {
|
|
16532
|
+
const normalized = rules.map((rule) => ({
|
|
16533
|
+
status_code: rule.status_code,
|
|
16534
|
+
path_pattern: normalizePathPattern(rule.path_pattern),
|
|
16535
|
+
methods: normalizeHttpMethods(rule.methods)
|
|
16536
|
+
}));
|
|
16537
|
+
const deduped = /* @__PURE__ */ new Map();
|
|
16538
|
+
for (const rule of normalized) {
|
|
16539
|
+
deduped.set(`${rule.status_code}:${rule.path_pattern}:${rule.methods.join(",")}`, rule);
|
|
16540
|
+
}
|
|
16541
|
+
return Array.from(deduped.values()).sort((left, right) => {
|
|
16542
|
+
if (left.status_code !== right.status_code) return left.status_code - right.status_code;
|
|
16543
|
+
const pathComparison = left.path_pattern.localeCompare(right.path_pattern);
|
|
16544
|
+
if (pathComparison !== 0) return pathComparison;
|
|
16545
|
+
return left.methods.join(",").localeCompare(right.methods.join(","));
|
|
16546
|
+
});
|
|
16547
|
+
}
|
|
16548
|
+
var ImmediateClientErrorPathRuleSchema = external_exports.object({
|
|
16549
|
+
status_code: ImmediateClientErrorStatusSchema,
|
|
16550
|
+
path_pattern: external_exports.string().min(1).max(256).transform(normalizePathPattern).refine(isValidPathPattern, {
|
|
16551
|
+
message: "path_pattern must start with / and may only use a terminal * wildcard"
|
|
16552
|
+
}),
|
|
16553
|
+
methods: external_exports.array(HttpMethodSchema).max(7).optional().default([]).transform(normalizeHttpMethods)
|
|
16554
|
+
});
|
|
16555
|
+
var ImmediateClientErrorPathRulesSchema = external_exports.array(ImmediateClientErrorPathRuleSchema).max(25).transform((rules) => normalizeImmediateClientErrorPathRules(rules));
|
|
16509
16556
|
var ResolvedCapturePolicySchema = external_exports.object({
|
|
16510
16557
|
preset: CapturePresetSchema,
|
|
16511
16558
|
capture_logs: CaptureLogsSchema,
|
|
16512
16559
|
capture_request_events: CaptureRequestEventsSchema,
|
|
16513
16560
|
capture_breadcrumbs: CaptureBreadcrumbsSchema,
|
|
16514
16561
|
capture_probe_events: CaptureProbeEventsSchema,
|
|
16515
|
-
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema
|
|
16562
|
+
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema,
|
|
16563
|
+
immediate_client_error_path_rules: ImmediateClientErrorPathRulesSchema.default([])
|
|
16516
16564
|
});
|
|
16517
16565
|
var CapturePolicyOverridesSchema = external_exports.object({
|
|
16518
16566
|
capture_logs: CaptureLogsSchema.nullable(),
|
|
16519
16567
|
capture_request_events: CaptureRequestEventsSchema.nullable(),
|
|
16520
16568
|
capture_breadcrumbs: CaptureBreadcrumbsSchema.nullable(),
|
|
16521
16569
|
capture_probe_events: CaptureProbeEventsSchema.nullable(),
|
|
16522
|
-
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema.nullable()
|
|
16570
|
+
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema.nullable(),
|
|
16571
|
+
immediate_client_error_path_rules: ImmediateClientErrorPathRulesSchema.nullable().default(null)
|
|
16523
16572
|
});
|
|
16524
16573
|
var CapturePolicyResponseSchema = external_exports.object({
|
|
16525
16574
|
access_mode: external_exports.enum(["manage", "preview"]),
|
|
@@ -16534,6 +16583,7 @@ var CapturePolicySchema = external_exports.object({
|
|
|
16534
16583
|
capture_breadcrumbs: CaptureBreadcrumbsSchema.nullable(),
|
|
16535
16584
|
capture_probe_events: CaptureProbeEventsSchema.nullable(),
|
|
16536
16585
|
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema.nullable(),
|
|
16586
|
+
immediate_client_error_path_rules: ImmediateClientErrorPathRulesSchema.nullable().default(null),
|
|
16537
16587
|
updated_at: external_exports.string().datetime()
|
|
16538
16588
|
});
|
|
16539
16589
|
var CapturePolicyUpdateSchema = external_exports.object({
|
|
@@ -16542,7 +16592,8 @@ var CapturePolicyUpdateSchema = external_exports.object({
|
|
|
16542
16592
|
capture_request_events: CaptureRequestEventsSchema.nullable().optional(),
|
|
16543
16593
|
capture_breadcrumbs: CaptureBreadcrumbsSchema.nullable().optional(),
|
|
16544
16594
|
capture_probe_events: CaptureProbeEventsSchema.nullable().optional(),
|
|
16545
|
-
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema.nullable().optional()
|
|
16595
|
+
immediate_client_error_statuses: ImmediateClientErrorStatusesSchema.nullable().optional(),
|
|
16596
|
+
immediate_client_error_path_rules: ImmediateClientErrorPathRulesSchema.nullable().optional()
|
|
16546
16597
|
});
|
|
16547
16598
|
var PRESET_DEFAULTS = {
|
|
16548
16599
|
minimal: {
|
|
@@ -16550,30 +16601,69 @@ var PRESET_DEFAULTS = {
|
|
|
16550
16601
|
capture_request_events: "failures_only",
|
|
16551
16602
|
capture_breadcrumbs: "local_only",
|
|
16552
16603
|
capture_probe_events: "buffer_only",
|
|
16553
|
-
immediate_client_error_statuses: []
|
|
16604
|
+
immediate_client_error_statuses: [],
|
|
16605
|
+
immediate_client_error_path_rules: []
|
|
16554
16606
|
},
|
|
16555
16607
|
balanced: {
|
|
16556
16608
|
capture_logs: "warning",
|
|
16557
16609
|
capture_request_events: "failures_only",
|
|
16558
16610
|
capture_breadcrumbs: "exception_only",
|
|
16559
16611
|
capture_probe_events: "buffer_only",
|
|
16560
|
-
immediate_client_error_statuses: []
|
|
16612
|
+
immediate_client_error_statuses: [],
|
|
16613
|
+
immediate_client_error_path_rules: []
|
|
16561
16614
|
},
|
|
16562
16615
|
investigative: {
|
|
16563
16616
|
capture_logs: "info",
|
|
16564
16617
|
capture_request_events: "all",
|
|
16565
16618
|
capture_breadcrumbs: "standalone",
|
|
16566
16619
|
capture_probe_events: "standalone_when_activated",
|
|
16567
|
-
immediate_client_error_statuses: [...RECOMMENDED_IMMEDIATE_CLIENT_ERROR_STATUSES]
|
|
16620
|
+
immediate_client_error_statuses: [...RECOMMENDED_IMMEDIATE_CLIENT_ERROR_STATUSES],
|
|
16621
|
+
immediate_client_error_path_rules: []
|
|
16568
16622
|
}
|
|
16569
16623
|
};
|
|
16570
16624
|
var BALANCED_IMMEDIATE_REQUEST_STATUSES = /* @__PURE__ */ new Set([408, 423, 424, 425, 429]);
|
|
16571
16625
|
var INVESTIGATIVE_IMMEDIATE_REQUEST_STATUSES = /* @__PURE__ */ new Set([...BALANCED_IMMEDIATE_REQUEST_STATUSES, 409]);
|
|
16572
|
-
|
|
16573
|
-
|
|
16574
|
-
|
|
16626
|
+
function normalizeRequestPath(value) {
|
|
16627
|
+
if (typeof value !== "string") {
|
|
16628
|
+
return null;
|
|
16629
|
+
}
|
|
16630
|
+
const trimmed = value.trim();
|
|
16631
|
+
if (trimmed.length === 0) {
|
|
16632
|
+
return null;
|
|
16633
|
+
}
|
|
16634
|
+
const path = trimmed.startsWith("http://") || trimmed.startsWith("https://") ? (() => {
|
|
16635
|
+
try {
|
|
16636
|
+
return new URL(trimmed).pathname;
|
|
16637
|
+
} catch {
|
|
16638
|
+
return trimmed;
|
|
16639
|
+
}
|
|
16640
|
+
})() : trimmed;
|
|
16641
|
+
return (path.split(/[?#]/, 1)[0] ?? path).replace(/\/{2,}/g, "/");
|
|
16642
|
+
}
|
|
16643
|
+
function pathPatternMatches(rulePattern, requestPath) {
|
|
16644
|
+
const pattern = normalizePathPattern(rulePattern);
|
|
16645
|
+
if (!pattern.endsWith("*")) {
|
|
16646
|
+
return requestPath === pattern;
|
|
16647
|
+
}
|
|
16648
|
+
const prefix = pattern.slice(0, -1);
|
|
16649
|
+
return requestPath.startsWith(prefix);
|
|
16650
|
+
}
|
|
16651
|
+
function matchesImmediateClientErrorPathRule(input) {
|
|
16652
|
+
const { responseStatus, immediateClientErrorPathRules = [] } = input;
|
|
16653
|
+
if (responseStatus === null || !Number.isFinite(responseStatus) || immediateClientErrorPathRules.length === 0) {
|
|
16654
|
+
return false;
|
|
16655
|
+
}
|
|
16656
|
+
const requestPath = normalizeRequestPath(input.requestPath);
|
|
16657
|
+
if (requestPath === null) {
|
|
16658
|
+
return false;
|
|
16659
|
+
}
|
|
16660
|
+
const httpMethod = typeof input.httpMethod === "string" ? input.httpMethod.toUpperCase() : null;
|
|
16661
|
+
return immediateClientErrorPathRules.some(
|
|
16662
|
+
(rule) => rule.status_code === responseStatus && (rule.methods.length === 0 || httpMethod !== null && rule.methods.includes(httpMethod)) && pathPatternMatches(rule.path_pattern, requestPath)
|
|
16663
|
+
);
|
|
16664
|
+
}
|
|
16575
16665
|
function classifyRequestStatus(input) {
|
|
16576
|
-
const { responseStatus, capturePreset, immediateClientErrorStatuses = [] } = input;
|
|
16666
|
+
const { responseStatus, capturePreset, immediateClientErrorStatuses = [], immediateClientErrorPathRules = [] } = input;
|
|
16577
16667
|
if (responseStatus === null || !Number.isFinite(responseStatus)) {
|
|
16578
16668
|
return "context_signal";
|
|
16579
16669
|
}
|
|
@@ -16583,6 +16673,14 @@ function classifyRequestStatus(input) {
|
|
|
16583
16673
|
if (immediateClientErrorStatuses.includes(responseStatus)) {
|
|
16584
16674
|
return "incident_signal";
|
|
16585
16675
|
}
|
|
16676
|
+
if (matchesImmediateClientErrorPathRule({
|
|
16677
|
+
responseStatus,
|
|
16678
|
+
requestPath: input.requestPath,
|
|
16679
|
+
httpMethod: input.httpMethod,
|
|
16680
|
+
immediateClientErrorPathRules
|
|
16681
|
+
})) {
|
|
16682
|
+
return "incident_signal";
|
|
16683
|
+
}
|
|
16586
16684
|
if (capturePreset === "investigative") {
|
|
16587
16685
|
return INVESTIGATIVE_IMMEDIATE_REQUEST_STATUSES.has(responseStatus) ? "incident_signal" : "context_signal";
|
|
16588
16686
|
}
|
|
@@ -16592,35 +16690,103 @@ function classifyRequestStatus(input) {
|
|
|
16592
16690
|
return "context_signal";
|
|
16593
16691
|
}
|
|
16594
16692
|
function getRequestAnomalyThreshold(input) {
|
|
16595
|
-
const { responseStatus
|
|
16693
|
+
const { responseStatus } = input;
|
|
16596
16694
|
if (responseStatus === null || !Number.isFinite(responseStatus) || responseStatus < 400 || responseStatus >= 500) {
|
|
16597
16695
|
return null;
|
|
16598
16696
|
}
|
|
16599
|
-
|
|
16600
|
-
|
|
16697
|
+
return null;
|
|
16698
|
+
}
|
|
16699
|
+
|
|
16700
|
+
// ../../packages/shared-types/src/request-failure-noise.ts
|
|
16701
|
+
function isLowValueExternalProbeRequestFailure404(input) {
|
|
16702
|
+
if (input.responseStatus !== 404 || input.httpMethod.toUpperCase() !== "GET") {
|
|
16703
|
+
return false;
|
|
16601
16704
|
}
|
|
16602
|
-
|
|
16603
|
-
|
|
16604
|
-
|
|
16605
|
-
|
|
16606
|
-
|
|
16705
|
+
const normalizedRoute = input.routeTemplate.toLowerCase().replace(/\/+$/, "") || "/";
|
|
16706
|
+
const normalizedPath = normalizePath(input.requestPath ?? input.routeTemplate);
|
|
16707
|
+
const routesToCheck = /* @__PURE__ */ new Set([normalizedRoute, normalizedPath]);
|
|
16708
|
+
for (const route of routesToCheck) {
|
|
16709
|
+
if (isRouteOnlyExternalProbe(route)) {
|
|
16710
|
+
return true;
|
|
16711
|
+
}
|
|
16607
16712
|
}
|
|
16608
|
-
|
|
16609
|
-
|
|
16610
|
-
|
|
16611
|
-
|
|
16612
|
-
|
|
16713
|
+
return isDirectIpRequest(input.headers ?? null) && [...routesToCheck].some(isGenericDirectIpProbeRoute);
|
|
16714
|
+
}
|
|
16715
|
+
function normalizePath(path) {
|
|
16716
|
+
const withoutQuery = path.split("?")[0] ?? path;
|
|
16717
|
+
return withoutQuery.toLowerCase().replace(/\/+$/, "") || "/";
|
|
16718
|
+
}
|
|
16719
|
+
function isRouteOnlyExternalProbe(normalizedRoute) {
|
|
16720
|
+
const exactRoutes = /* @__PURE__ */ new Set([
|
|
16721
|
+
"/.env",
|
|
16722
|
+
"/__debug__/render_panel",
|
|
16723
|
+
"/actuator",
|
|
16724
|
+
"/autodiscover/autodiscover.json",
|
|
16725
|
+
"/developmentserver/metadatauploader",
|
|
16726
|
+
"/cpanel",
|
|
16727
|
+
"/favicon.ico",
|
|
16728
|
+
"/geoserver/web",
|
|
16729
|
+
"/hnap1",
|
|
16730
|
+
"/logon/logonpoint/index.html",
|
|
16731
|
+
"/owa/auth/logon.aspx",
|
|
16732
|
+
"/robots.txt",
|
|
16733
|
+
"/rdweb/pages",
|
|
16734
|
+
"/web",
|
|
16735
|
+
"/webclient/login.xhtml",
|
|
16736
|
+
"/webconsole",
|
|
16737
|
+
"/webui",
|
|
16738
|
+
"/whm",
|
|
16739
|
+
"/wp-admin",
|
|
16740
|
+
"/wp-login.php",
|
|
16741
|
+
"/wsman",
|
|
16742
|
+
"/xmlrpc.php"
|
|
16743
|
+
]);
|
|
16744
|
+
if (exactRoutes.has(normalizedRoute)) {
|
|
16745
|
+
return true;
|
|
16613
16746
|
}
|
|
16614
|
-
|
|
16615
|
-
|
|
16616
|
-
|
|
16617
|
-
|
|
16618
|
-
|
|
16747
|
+
return normalizedRoute.includes("/.git/") || normalizedRoute.includes("/.svn/") || normalizedRoute.includes("/api_keys") || normalizedRoute.includes("/backup/api_keys") || normalizedRoute.includes("/phpmyadmin") || normalizedRoute.includes("/pma/") || normalizedRoute.includes("/vendor/phpunit/") || normalizedRoute.startsWith("/autodiscover/") || normalizedRoute.startsWith("/cgi-bin/") || normalizedRoute.startsWith("/ecp/") || normalizedRoute.endsWith("/.git/config") || normalizedRoute.endsWith("/composer.json") || normalizedRoute.endsWith("/composer.lock") || normalizedRoute.endsWith("/package-lock.json") || normalizedRoute.endsWith("/package.json") || normalizedRoute.endsWith("/server-status") || normalizedRoute.includes("wp-config") || normalizedRoute.startsWith("/owa/") || normalizedRoute.startsWith("/rdweb/") || normalizedRoute.startsWith("/vpn/") || normalizedRoute.startsWith("/wp-") || isSensitiveBackupFileProbe(normalizedRoute);
|
|
16748
|
+
}
|
|
16749
|
+
function isSensitiveBackupFileProbe(normalizedRoute) {
|
|
16750
|
+
if (!/\.(?:bak|backup|dump|old|orig|save|sql|swp|tar|tar\.gz|zip)$/.test(normalizedRoute)) {
|
|
16751
|
+
return false;
|
|
16752
|
+
}
|
|
16753
|
+
return /(?:^|\/|\.)(?:backup|config|database|db|dump|env|secret|site|www|wp-config)(?:\/|\.|_|-|$)/.test(normalizedRoute);
|
|
16754
|
+
}
|
|
16755
|
+
function isGenericDirectIpProbeRoute(normalizedRoute) {
|
|
16756
|
+
return [
|
|
16757
|
+
"/admin",
|
|
16758
|
+
"/administrator",
|
|
16759
|
+
"/login",
|
|
16760
|
+
"/logincheck",
|
|
16761
|
+
"/remote/logincheck"
|
|
16762
|
+
].includes(normalizedRoute);
|
|
16763
|
+
}
|
|
16764
|
+
function isDirectIpRequest(headers) {
|
|
16765
|
+
if (headers === null) {
|
|
16766
|
+
return false;
|
|
16767
|
+
}
|
|
16768
|
+
const host = readHeader(headers, "x-forwarded-host") ?? readHeader(headers, "host");
|
|
16769
|
+
if (host === null) {
|
|
16770
|
+
return false;
|
|
16771
|
+
}
|
|
16772
|
+
return isIpLikeHost(host);
|
|
16773
|
+
}
|
|
16774
|
+
function readHeader(headers, name) {
|
|
16775
|
+
const direct = headers[name] ?? headers[name.toLowerCase()];
|
|
16776
|
+
if (typeof direct === "string") {
|
|
16777
|
+
return direct;
|
|
16778
|
+
}
|
|
16779
|
+
if (Array.isArray(direct) && typeof direct[0] === "string") {
|
|
16780
|
+
return direct[0];
|
|
16619
16781
|
}
|
|
16620
16782
|
return null;
|
|
16621
16783
|
}
|
|
16784
|
+
function isIpLikeHost(value) {
|
|
16785
|
+
const host = value.trim().replace(/:\d+$/, "");
|
|
16786
|
+
return /^(?:\d{1,3}\.){3}\d{1,3}$/.test(host) || /^\[[0-9a-f:]+\]$/i.test(host) || host.includes(":") && /^[0-9a-f:]+$/i.test(host);
|
|
16787
|
+
}
|
|
16622
16788
|
|
|
16623
|
-
// ../../packages/shared-types/src/capture-
|
|
16789
|
+
// ../../packages/shared-types/src/capture-rule-schemas.ts
|
|
16624
16790
|
var CAPTURE_RULE_EVENT_TYPES = [
|
|
16625
16791
|
"backend_exception",
|
|
16626
16792
|
"request_event",
|
|
@@ -16648,6 +16814,7 @@ var CaptureRuleSampleEventClassSchema = external_exports.enum(CaptureRuleSampleE
|
|
|
16648
16814
|
var CaptureRuleRuntimeSchema = external_exports.enum(CAPTURE_RULE_RUNTIME_VALUES);
|
|
16649
16815
|
var CaptureRuleEventTypeSchema = external_exports.enum(CAPTURE_RULE_EVENT_TYPES);
|
|
16650
16816
|
var BrowserEventKindSchema = external_exports.enum(["window_error", "resource_error"]);
|
|
16817
|
+
var CaptureRuleClientKindSchema = external_exports.enum(["human", "bot", "unknown"]);
|
|
16651
16818
|
function normalizeOptionalTrimmedString(value) {
|
|
16652
16819
|
const trimmed = value?.trim();
|
|
16653
16820
|
return trimmed && trimmed.length > 0 ? trimmed : void 0;
|
|
@@ -16725,6 +16892,9 @@ var CaptureRuleMatcherSchema = external_exports.object({
|
|
|
16725
16892
|
message_contains: external_exports.string().min(1).max(500).optional(),
|
|
16726
16893
|
message_equals: external_exports.string().min(1).max(500).optional(),
|
|
16727
16894
|
browser_event_kind: BrowserEventKindSchema.optional(),
|
|
16895
|
+
browser_event_opaque: external_exports.boolean().optional(),
|
|
16896
|
+
client_kind: CaptureRuleClientKindSchema.optional(),
|
|
16897
|
+
bot_family: external_exports.string().min(1).max(120).optional(),
|
|
16728
16898
|
resource_url: UrlMatcherSchema.optional(),
|
|
16729
16899
|
request_url: UrlMatcherSchema.optional(),
|
|
16730
16900
|
status_codes: external_exports.array(external_exports.number().int().min(100).max(599)).min(1).optional(),
|
|
@@ -16739,6 +16909,7 @@ var CaptureRuleMatcherSchema = external_exports.object({
|
|
|
16739
16909
|
const errorName = normalizeOptionalTrimmedString(value.error_name);
|
|
16740
16910
|
const messageContains = normalizeOptionalTrimmedString(value.message_contains);
|
|
16741
16911
|
const messageEquals = normalizeOptionalTrimmedString(value.message_equals);
|
|
16912
|
+
const botFamily = normalizeOptionalTrimmedString(value.bot_family);
|
|
16742
16913
|
const statusCodes = normalizeNumberArray(value.status_codes);
|
|
16743
16914
|
if (eventTypes !== void 0) {
|
|
16744
16915
|
normalized.event_types = eventTypes;
|
|
@@ -16767,6 +16938,15 @@ var CaptureRuleMatcherSchema = external_exports.object({
|
|
|
16767
16938
|
if (value.browser_event_kind !== void 0) {
|
|
16768
16939
|
normalized.browser_event_kind = value.browser_event_kind;
|
|
16769
16940
|
}
|
|
16941
|
+
if (value.browser_event_opaque !== void 0) {
|
|
16942
|
+
normalized.browser_event_opaque = value.browser_event_opaque;
|
|
16943
|
+
}
|
|
16944
|
+
if (value.client_kind !== void 0) {
|
|
16945
|
+
normalized.client_kind = value.client_kind;
|
|
16946
|
+
}
|
|
16947
|
+
if (botFamily !== void 0) {
|
|
16948
|
+
normalized.bot_family = botFamily;
|
|
16949
|
+
}
|
|
16770
16950
|
if (value.resource_url !== void 0) {
|
|
16771
16951
|
normalized.resource_url = value.resource_url;
|
|
16772
16952
|
}
|
|
@@ -16793,6 +16973,9 @@ var CaptureRuleMatcherSchema = external_exports.object({
|
|
|
16793
16973
|
"message_contains",
|
|
16794
16974
|
"message_equals",
|
|
16795
16975
|
"browser_event_kind",
|
|
16976
|
+
"browser_event_opaque",
|
|
16977
|
+
"client_kind",
|
|
16978
|
+
"bot_family",
|
|
16796
16979
|
"resource_url",
|
|
16797
16980
|
"request_url",
|
|
16798
16981
|
"status_codes",
|
|
@@ -16975,6 +17158,8 @@ var CaptureRulesFileSchema = external_exports.object({
|
|
|
16975
17158
|
version: external_exports.literal(1),
|
|
16976
17159
|
rules: external_exports.array(CaptureRuleSchema)
|
|
16977
17160
|
});
|
|
17161
|
+
|
|
17162
|
+
// ../../packages/shared-types/src/capture-rule-evaluation.ts
|
|
16978
17163
|
var CaptureRuleEvaluationUrlSchema = external_exports.object({
|
|
16979
17164
|
host: external_exports.string().min(1).transform((value) => value.toLowerCase()).optional(),
|
|
16980
17165
|
path: external_exports.string().min(1).transform((value) => value.startsWith("/") ? value : `/${value}`)
|
|
@@ -16990,11 +17175,40 @@ var CaptureRuleEvaluationContextSchema = external_exports.object({
|
|
|
16990
17175
|
error_name: external_exports.string().min(1).optional(),
|
|
16991
17176
|
message: external_exports.string().min(1).optional(),
|
|
16992
17177
|
browser_event_kind: BrowserEventKindSchema.optional(),
|
|
17178
|
+
browser_event_opaque: external_exports.boolean().optional(),
|
|
17179
|
+
client_kind: CaptureRuleClientKindSchema.optional(),
|
|
17180
|
+
bot_family: external_exports.string().min(1).max(120).optional(),
|
|
16993
17181
|
resource_url: CaptureRuleEvaluationUrlSchema.optional(),
|
|
16994
17182
|
request_url: CaptureRuleEvaluationUrlSchema.optional(),
|
|
16995
17183
|
status_code: external_exports.number().int().min(0).max(599).optional(),
|
|
16996
17184
|
fingerprint: CaptureRuleFingerprintSchema.optional()
|
|
16997
17185
|
});
|
|
17186
|
+
function classifyCaptureRuleClientFromUserAgent(userAgent) {
|
|
17187
|
+
if (userAgent === null || userAgent === void 0) {
|
|
17188
|
+
return { client_kind: "unknown" };
|
|
17189
|
+
}
|
|
17190
|
+
const lower = userAgent.toLowerCase();
|
|
17191
|
+
const knownBots = [
|
|
17192
|
+
{ family: "Googlebot", markers: ["googlebot", "adsbot-google", "google-inspectiontool"] },
|
|
17193
|
+
{ family: "Bingbot", markers: ["bingbot", "msnbot"] },
|
|
17194
|
+
{ family: "DuckDuckBot", markers: ["duckduckbot"] },
|
|
17195
|
+
{ family: "Applebot", markers: ["applebot"] },
|
|
17196
|
+
{ family: "YandexBot", markers: ["yandexbot"] },
|
|
17197
|
+
{ family: "Baiduspider", markers: ["baiduspider"] },
|
|
17198
|
+
{ family: "FacebookBot", markers: ["facebookexternalhit", "facebot"] },
|
|
17199
|
+
{ family: "LinkedInBot", markers: ["linkedinbot"] },
|
|
17200
|
+
{ family: "TwitterBot", markers: ["twitterbot"] },
|
|
17201
|
+
{ family: "Slackbot", markers: ["slackbot"] }
|
|
17202
|
+
];
|
|
17203
|
+
const knownBot = knownBots.find((entry) => entry.markers.some((marker) => lower.includes(marker)));
|
|
17204
|
+
if (knownBot !== void 0) {
|
|
17205
|
+
return { client_kind: "bot", bot_family: knownBot.family };
|
|
17206
|
+
}
|
|
17207
|
+
if (["bot", "crawler", "spider", "slurp"].some((marker) => lower.includes(marker))) {
|
|
17208
|
+
return { client_kind: "bot", bot_family: "OtherBot" };
|
|
17209
|
+
}
|
|
17210
|
+
return { client_kind: "human" };
|
|
17211
|
+
}
|
|
16998
17212
|
|
|
16999
17213
|
// ../../packages/shared-types/src/capture-rule-suggestions.ts
|
|
17000
17214
|
var CaptureRuleSuggestionConfidenceSchema = external_exports.enum(["high", "medium", "low"]);
|
|
@@ -17204,6 +17418,12 @@ var BrowserExceptionEventSchema = external_exports.object({
|
|
|
17204
17418
|
}).strict().optional(),
|
|
17205
17419
|
opaque: external_exports.boolean()
|
|
17206
17420
|
}).strict();
|
|
17421
|
+
var FrontendRejectionReasonSchema = external_exports.object({
|
|
17422
|
+
kind: external_exports.enum(["error", "string", "object", "null", "undefined", "unknown"]),
|
|
17423
|
+
name: external_exports.string().min(1).optional(),
|
|
17424
|
+
message: external_exports.string().min(1).optional(),
|
|
17425
|
+
preview: external_exports.string().min(1).optional()
|
|
17426
|
+
}).strict();
|
|
17207
17427
|
var FrontendExceptionPayloadSchema = external_exports.object({
|
|
17208
17428
|
name: external_exports.string().min(1),
|
|
17209
17429
|
message: external_exports.string().min(1),
|
|
@@ -17216,6 +17436,7 @@ var FrontendExceptionPayloadSchema = external_exports.object({
|
|
|
17216
17436
|
breadcrumbs: external_exports.array(FrontendExceptionBreadcrumbSchema).optional(),
|
|
17217
17437
|
device: DeviceInfoSchema.nullable().optional(),
|
|
17218
17438
|
browser_event: BrowserExceptionEventSchema.optional(),
|
|
17439
|
+
rejection_reason: FrontendRejectionReasonSchema.optional(),
|
|
17219
17440
|
dom_context: external_exports.object({
|
|
17220
17441
|
mode: external_exports.literal("lightweight"),
|
|
17221
17442
|
html_excerpt: external_exports.string().min(1)
|
|
@@ -17650,7 +17871,7 @@ function buildSkill() {
|
|
|
17650
17871
|
"2. Inspect the incident bundle and reproduction artifact before proposing a fix.",
|
|
17651
17872
|
"3. Run `debugbundle analyze --type improvement --local` after local processing when you need a deterministic change plan.",
|
|
17652
17873
|
"4. Apply the narrowest fix, then validate it with the repository test workflow from `.debugbundle/profile.json`.",
|
|
17653
|
-
"5. When the fix is confirmed, or when the incident was intentionally generated for smoke, verification, or dogfooding, resolve it with `debugbundle resolve <incident-id
|
|
17874
|
+
"5. When the fix is confirmed, or when the incident was intentionally generated for smoke, verification, or dogfooding, resolve it with `debugbundle resolve <incident-id> [incident-id ...]` or MCP `resolve_incident` / `resolve_incidents` so the open queue stays actionable.",
|
|
17654
17875
|
"",
|
|
17655
17876
|
"## Incident Hygiene",
|
|
17656
17877
|
"",
|
|
@@ -17659,6 +17880,15 @@ function buildSkill() {
|
|
|
17659
17880
|
"- Reopen or leave open if the failure is still present, the validation is incomplete, or the incident represents a live unresolved problem.",
|
|
17660
17881
|
"- If a resolved incident regresses, let the platform move it back to `regressed` through normal incident lifecycle behavior.",
|
|
17661
17882
|
"",
|
|
17883
|
+
"## Noise Management",
|
|
17884
|
+
"",
|
|
17885
|
+
"When incident evidence shows repeated low-value operational noise rather than a product bug, evaluate whether a scoped capture rule or capture-policy path rule should handle future matches.",
|
|
17886
|
+
"",
|
|
17887
|
+
"- Run `debugbundle capture-rule suggest <incident-id> --json` before creating a manual rule. Apply deterministic suggestions with `debugbundle capture-rule create-from-suggestion <incident-id> --suggestion-id <id>` after confirming the scope is safe.",
|
|
17888
|
+
"- Prefer project capture rules for operational noise because they are centralized, auditable, and enforced by ingestion and processing. Use SDK `beforeSend` only for app-owned local policy such as final redaction or events that must never leave the runtime.",
|
|
17889
|
+
"- 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.",
|
|
17890
|
+
"- 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>`.",
|
|
17891
|
+
"",
|
|
17662
17892
|
"## Profile Validation",
|
|
17663
17893
|
"",
|
|
17664
17894
|
"Use this task after setup or whenever architecture changes make the static profile stale.",
|
|
@@ -17721,10 +17951,21 @@ function buildCliReference() {
|
|
|
17721
17951
|
"- `debugbundle explain <incident-id> [--source <local|cloud>] [--json]`",
|
|
17722
17952
|
"- `debugbundle bundle <incident-id> [--source <local|cloud>] [--json]`",
|
|
17723
17953
|
"- `debugbundle reproduce <incident-id> [--source <local|cloud>] [--json]`",
|
|
17724
|
-
"- `debugbundle resolve <incident-id> [--source <local|cloud>] [--json]`",
|
|
17725
|
-
"- `debugbundle reopen <incident-id> [--source <local|cloud>] [--json]`",
|
|
17954
|
+
"- `debugbundle resolve <incident-id> [incident-id ...] [--source <local|cloud>] [--json]`",
|
|
17955
|
+
"- `debugbundle reopen <incident-id> [incident-id ...] [--source <local|cloud>] [--json]`",
|
|
17726
17956
|
"- `debugbundle analyze --type improvement --local`",
|
|
17727
17957
|
"",
|
|
17958
|
+
"## Noise Management",
|
|
17959
|
+
"",
|
|
17960
|
+
"- `debugbundle capture-rule suggest <incident-id> [--auth-file <path>] [--json]`",
|
|
17961
|
+
"- `debugbundle capture-rule create-from-suggestion <incident-id> --suggestion-id <id> [--name <name>] [--expires-at <ISO8601>] [--auth-file <path>] [--json]`",
|
|
17962
|
+
"- `debugbundle capture-rule list --project-id <id> [--auth-file <path>] [--json]`",
|
|
17963
|
+
"- `debugbundle capture-rule create --project-id <id> --name <name> --action <demote|sample|drop> --matcher-json <json> [--auth-file <path>] [--json]`",
|
|
17964
|
+
"- `debugbundle capture-policy get [--project <id>] [--json]`",
|
|
17965
|
+
"- `debugbundle capture-policy set [--project <id>] --client-error-path-rule <404=/path/*@GET,POST> [--json]`",
|
|
17966
|
+
"",
|
|
17967
|
+
"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.",
|
|
17968
|
+
"",
|
|
17728
17969
|
"## Operational Paths",
|
|
17729
17970
|
"",
|
|
17730
17971
|
"- `.debugbundle/profile.json` \u2014 committed project map and agent validation state",
|
|
@@ -17755,7 +17996,7 @@ function buildCliReference() {
|
|
|
17755
17996
|
"```bash",
|
|
17756
17997
|
"debugbundle incidents --status open --json \\",
|
|
17757
17998
|
` | jq -r '.incidents[] | select(.title | test("smoke test|dogfood|verification|synthetic"; "i")) | .incident_id' \\`,
|
|
17758
|
-
" | xargs
|
|
17999
|
+
" | xargs debugbundle resolve",
|
|
17759
18000
|
"```",
|
|
17760
18001
|
""
|
|
17761
18002
|
].join("\n");
|
|
@@ -17774,19 +18015,28 @@ function buildMcpReference() {
|
|
|
17774
18015
|
"- `get_incident_context` \u2014 fetch deterministic explanation context for triage.",
|
|
17775
18016
|
"- `get_bundle` \u2014 fetch the full debug bundle before proposing a fix.",
|
|
17776
18017
|
"- `get_reproduction` \u2014 fetch reproduction guidance before editing code.",
|
|
17777
|
-
"- `resolve_incident` / `reopen_incident` \u2014 update lifecycle state after validation.",
|
|
18018
|
+
"- `resolve_incident` / `resolve_incidents` / `reopen_incident` / `reopen_incidents` \u2014 update lifecycle state after validation.",
|
|
17778
18019
|
"- `analyze` \u2014 run local agent-oriented analysis from local bundles and skill schemas.",
|
|
17779
18020
|
"",
|
|
17780
18021
|
"- Prefer bundle retrieval tools before reading raw repository files.",
|
|
17781
18022
|
"- Use MCP bundle access when the current issue originated in production.",
|
|
17782
|
-
"- Resolve fixed or intentionally generated incidents with `resolve_incident` so open incidents stay actionable.",
|
|
18023
|
+
"- Resolve fixed or intentionally generated incidents with `resolve_incident` or `resolve_incidents` so open incidents stay actionable.",
|
|
17783
18024
|
"- Fall back to local CLI processing when the project is local-only.",
|
|
17784
18025
|
"",
|
|
18026
|
+
"## Noise and Capture Policy Tools",
|
|
18027
|
+
"",
|
|
18028
|
+
"- `suggest_capture_rules_from_incident` \u2014 generate deterministic capture-rule suggestions from an incident bundle.",
|
|
18029
|
+
"- `create_capture_rule_from_incident_suggestion` \u2014 apply a confirmed suggestion.",
|
|
18030
|
+
"- `list_capture_rules`, `create_capture_rule`, `update_capture_rule`, `delete_capture_rule` \u2014 manage project capture rules.",
|
|
18031
|
+
"- `get_capture_policy`, `update_capture_policy` \u2014 review or update capture policy, including path-scoped client-error incident rules.",
|
|
18032
|
+
"",
|
|
18033
|
+
"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.",
|
|
18034
|
+
"",
|
|
17785
18035
|
"## Smoke-Test Cleanup Recipe",
|
|
17786
18036
|
"",
|
|
17787
18037
|
'1. Call `list_incidents` with `status: "open"`.',
|
|
17788
18038
|
"2. Filter incidents whose titles show they were intentionally generated for smoke, dogfood, verification, or synthetic checks.",
|
|
17789
|
-
"3. Call `
|
|
18039
|
+
"3. Call `resolve_incidents` for verified synthetic incidents, or `resolve_incident` for a single incident.",
|
|
17790
18040
|
"4. Call `list_incidents` again and confirm the open queue only contains actionable failures.",
|
|
17791
18041
|
""
|
|
17792
18042
|
].join("\n");
|
|
@@ -17906,6 +18156,16 @@ function buildSkillEvals() {
|
|
|
17906
18156
|
"Leave unresolved incidents open when the failure is still live or unverified."
|
|
17907
18157
|
]
|
|
17908
18158
|
},
|
|
18159
|
+
{
|
|
18160
|
+
name: "noise_management_guidance",
|
|
18161
|
+
prompt: "The same low-value frontend incident keeps reopening. Confirm the skill tells the agent how to evaluate operational noise without hiding real bugs.",
|
|
18162
|
+
expected_behavior: [
|
|
18163
|
+
"Inspect incident evidence before creating a rule.",
|
|
18164
|
+
"Use capture-rule suggestions for repeated operational noise.",
|
|
18165
|
+
"Keep generic frontend suppression narrow with structured browser or bot signals.",
|
|
18166
|
+
"Use capture-policy path rules for known route-scoped 4xx incidents."
|
|
18167
|
+
]
|
|
18168
|
+
},
|
|
17909
18169
|
{
|
|
17910
18170
|
name: "artifact_path_discovery",
|
|
17911
18171
|
prompt: "The user reports an unknown local runtime error. Confirm the skill tells the agent which DebugBundle paths and commands to inspect first.",
|
|
@@ -19236,7 +19496,7 @@ function getRequestResponseStatus(payload) {
|
|
|
19236
19496
|
const status = payload?.["response_status"];
|
|
19237
19497
|
return typeof status === "number" && Number.isFinite(status) ? status : null;
|
|
19238
19498
|
}
|
|
19239
|
-
function classifyEvent(eventType, logLevel, probeActivationId, payload, capturePreset = "minimal", immediateClientErrorStatuses = []) {
|
|
19499
|
+
function classifyEvent(eventType, logLevel, probeActivationId, payload, capturePreset = "minimal", immediateClientErrorStatuses = [], immediateClientErrorPathRules = []) {
|
|
19240
19500
|
switch (eventType) {
|
|
19241
19501
|
case "backend_exception":
|
|
19242
19502
|
case "frontend_exception":
|
|
@@ -19248,7 +19508,14 @@ function classifyEvent(eventType, logLevel, probeActivationId, payload, captureP
|
|
|
19248
19508
|
return "context_signal";
|
|
19249
19509
|
case "request_event": {
|
|
19250
19510
|
const responseStatus = getRequestResponseStatus(payload);
|
|
19251
|
-
return classifyRequestStatus({
|
|
19511
|
+
return classifyRequestStatus({
|
|
19512
|
+
responseStatus,
|
|
19513
|
+
requestPath: payload?.["path"],
|
|
19514
|
+
httpMethod: payload?.["method"],
|
|
19515
|
+
capturePreset,
|
|
19516
|
+
immediateClientErrorStatuses,
|
|
19517
|
+
immediateClientErrorPathRules
|
|
19518
|
+
});
|
|
19252
19519
|
}
|
|
19253
19520
|
case "frontend_breadcrumb":
|
|
19254
19521
|
case "deploy_metadata":
|
|
@@ -19955,6 +20222,33 @@ function buildRedactionRecord(bundleBody) {
|
|
|
19955
20222
|
notes: readString(redaction["notes"])
|
|
19956
20223
|
};
|
|
19957
20224
|
}
|
|
20225
|
+
function buildBrowserSignalRecord(bundleBody) {
|
|
20226
|
+
const bundle = isRecord(bundleBody) ? bundleBody : {};
|
|
20227
|
+
const context = isRecord(bundle["context"]) ? bundle["context"] : {};
|
|
20228
|
+
const frontend = isRecord(context["frontend"]) ? context["frontend"] : {};
|
|
20229
|
+
const exceptions = Array.isArray(frontend["exceptions"]) ? frontend["exceptions"] : [];
|
|
20230
|
+
let exception;
|
|
20231
|
+
for (let index = exceptions.length - 1; index >= 0; index -= 1) {
|
|
20232
|
+
const candidate = exceptions[index];
|
|
20233
|
+
if (isRecord(candidate) && isRecord(candidate["browser_event"])) {
|
|
20234
|
+
exception = candidate;
|
|
20235
|
+
break;
|
|
20236
|
+
}
|
|
20237
|
+
}
|
|
20238
|
+
const browserEvent = isRecord(exception) && isRecord(exception["browser_event"]) ? exception["browser_event"] : null;
|
|
20239
|
+
const device = isRecord(context["device"]) ? context["device"] : {};
|
|
20240
|
+
const client = classifyCaptureRuleClientFromUserAgent(readString(device["user_agent"]) ?? void 0);
|
|
20241
|
+
if (browserEvent === null && client.client_kind === "unknown") {
|
|
20242
|
+
return null;
|
|
20243
|
+
}
|
|
20244
|
+
return {
|
|
20245
|
+
browser_event_kind: readString(browserEvent?.["kind"]),
|
|
20246
|
+
browser_event_opaque: readBoolean(browserEvent?.["opaque"]),
|
|
20247
|
+
browser_event_message: readString(browserEvent?.["message"]),
|
|
20248
|
+
client_kind: client.client_kind,
|
|
20249
|
+
bot_family: client.bot_family ?? null
|
|
20250
|
+
};
|
|
20251
|
+
}
|
|
19958
20252
|
function buildVisibilityRecord(input) {
|
|
19959
20253
|
const routeTarget = input.primarySignal.route_template ?? input.primarySignal.request_path;
|
|
19960
20254
|
const matchedFields = input.incident.matched_fields.length === 0 ? "none" : input.incident.matched_fields.join(", ");
|
|
@@ -19992,6 +20286,14 @@ function buildSuggestedNextChecks(input) {
|
|
|
19992
20286
|
if (input.deploy.regression_window === true || input.incident.status === "regressed") {
|
|
19993
20287
|
suggestions.push("Compare this incident against the most recent deploy and recent regressions.");
|
|
19994
20288
|
}
|
|
20289
|
+
if (input.browserSignal?.browser_event_opaque === true) {
|
|
20290
|
+
suggestions.push("Treat the browser event as opaque; inspect CSP, cross-origin scripts, resource loading, and framework error boundaries before changing application code.");
|
|
20291
|
+
}
|
|
20292
|
+
if (input.browserSignal?.client_kind === "bot") {
|
|
20293
|
+
suggestions.push(
|
|
20294
|
+
`Review whether ${input.browserSignal.bot_family ?? "bot"} traffic is operational noise before applying a bot-scoped capture rule.`
|
|
20295
|
+
);
|
|
20296
|
+
}
|
|
19995
20297
|
if (input.reproduction.status === "pending") {
|
|
19996
20298
|
suggestions.push("Recheck reproduction guidance after the reproduction artifact is ready.");
|
|
19997
20299
|
}
|
|
@@ -20012,6 +20314,7 @@ function buildIncidentContextRecord(input) {
|
|
|
20012
20314
|
primarySignal
|
|
20013
20315
|
});
|
|
20014
20316
|
const redaction = buildRedactionRecord(bundleBody);
|
|
20317
|
+
const browserSignal = buildBrowserSignalRecord(bundleBody);
|
|
20015
20318
|
return {
|
|
20016
20319
|
incident: input.incident,
|
|
20017
20320
|
incident_reason: incidentReason,
|
|
@@ -20027,13 +20330,15 @@ function buildIncidentContextRecord(input) {
|
|
|
20027
20330
|
},
|
|
20028
20331
|
visibility,
|
|
20029
20332
|
redaction,
|
|
20333
|
+
browser_signal: browserSignal,
|
|
20030
20334
|
suggested_next_checks: buildSuggestedNextChecks({
|
|
20031
20335
|
incident: input.incident,
|
|
20032
20336
|
bundle: input.bundle,
|
|
20033
20337
|
reproduction: input.reproduction,
|
|
20034
20338
|
logs,
|
|
20035
20339
|
primarySignal,
|
|
20036
|
-
deploy
|
|
20340
|
+
deploy,
|
|
20341
|
+
browserSignal
|
|
20037
20342
|
})
|
|
20038
20343
|
};
|
|
20039
20344
|
}
|
|
@@ -20445,6 +20750,7 @@ var STORAGE_BOOTSTRAP_STATEMENTS = [
|
|
|
20445
20750
|
capture_breadcrumbs text,
|
|
20446
20751
|
capture_probe_events text,
|
|
20447
20752
|
immediate_client_error_statuses jsonb,
|
|
20753
|
+
immediate_client_error_path_rules jsonb,
|
|
20448
20754
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
20449
20755
|
)
|
|
20450
20756
|
`,
|
|
@@ -21800,6 +22106,13 @@ var STORAGE_SCHEMA_MIGRATIONS = [
|
|
|
21800
22106
|
ON plan_cleanup_tasks (completed_at, next_attempt_at, created_at)
|
|
21801
22107
|
`
|
|
21802
22108
|
]
|
|
22109
|
+
}),
|
|
22110
|
+
defineStorageSchemaMigration({
|
|
22111
|
+
id: "202606080001_add_capture_policy_client_error_path_rules",
|
|
22112
|
+
description: "Add path-scoped client error incident promotion rules to capture policies.",
|
|
22113
|
+
statements: [
|
|
22114
|
+
"ALTER TABLE capture_policies ADD COLUMN IF NOT EXISTS immediate_client_error_path_rules jsonb"
|
|
22115
|
+
]
|
|
21803
22116
|
})
|
|
21804
22117
|
];
|
|
21805
22118
|
|
|
@@ -23080,6 +23393,15 @@ function collectRequestAnomalyAggregates(batches, capturePreset) {
|
|
|
23080
23393
|
if (threshold === null || responseStatus === null || method === null || routeTemplate === null) {
|
|
23081
23394
|
continue;
|
|
23082
23395
|
}
|
|
23396
|
+
if (isLowValueExternalProbeRequestFailure404({
|
|
23397
|
+
httpMethod: method,
|
|
23398
|
+
requestPath: event.payload.path,
|
|
23399
|
+
routeTemplate,
|
|
23400
|
+
responseStatus,
|
|
23401
|
+
headers: event.payload.headers
|
|
23402
|
+
})) {
|
|
23403
|
+
continue;
|
|
23404
|
+
}
|
|
23083
23405
|
const projectId = requireProjectId(event);
|
|
23084
23406
|
const incidentFingerprint = buildRequestAnomalyFingerprint({
|
|
23085
23407
|
projectId,
|
|
@@ -28486,7 +28808,7 @@ var zodToJsonSchema = (schema, options) => {
|
|
|
28486
28808
|
var package_default = {
|
|
28487
28809
|
name: "@debugbundle/mcp",
|
|
28488
28810
|
mcpName: "com.debugbundle/mcp",
|
|
28489
|
-
version: "1.
|
|
28811
|
+
version: "1.3.0",
|
|
28490
28812
|
private: false,
|
|
28491
28813
|
description: "Model Context Protocol server for DebugBundle",
|
|
28492
28814
|
license: "AGPL-3.0-only",
|
|
@@ -29247,7 +29569,12 @@ var MCP_TOOL_CATALOG = [
|
|
|
29247
29569
|
capture_request_events: external_exports.string().nullable().optional(),
|
|
29248
29570
|
capture_breadcrumbs: external_exports.string().nullable().optional(),
|
|
29249
29571
|
capture_probe_events: external_exports.string().nullable().optional(),
|
|
29250
|
-
immediate_client_error_statuses: external_exports.array(external_exports.number().int().min(400).max(499)).nullable().optional()
|
|
29572
|
+
immediate_client_error_statuses: external_exports.array(external_exports.number().int().min(400).max(499)).nullable().optional(),
|
|
29573
|
+
immediate_client_error_path_rules: external_exports.array(external_exports.object({
|
|
29574
|
+
status_code: external_exports.number().int().min(400).max(499),
|
|
29575
|
+
path_pattern: external_exports.string(),
|
|
29576
|
+
methods: external_exports.array(external_exports.enum(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"])).optional()
|
|
29577
|
+
})).nullable().optional()
|
|
29251
29578
|
})
|
|
29252
29579
|
})
|
|
29253
29580
|
},
|
package/package.json
CHANGED
package/server.json
CHANGED
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
"source": "github",
|
|
9
9
|
"subfolder": "apps/mcp"
|
|
10
10
|
},
|
|
11
|
-
"version": "1.
|
|
11
|
+
"version": "1.3.0",
|
|
12
12
|
"packages": [
|
|
13
13
|
{
|
|
14
14
|
"registryType": "npm",
|
|
15
15
|
"registryBaseUrl": "https://registry.npmjs.org",
|
|
16
16
|
"identifier": "@debugbundle/mcp",
|
|
17
|
-
"version": "1.
|
|
17
|
+
"version": "1.3.0",
|
|
18
18
|
"transport": {
|
|
19
19
|
"type": "stdio"
|
|
20
20
|
},
|