@debugbundle/mcp 0.1.8 → 0.1.9
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/README.md +2 -0
- package/dist/main.cjs +2108 -141
- package/package.json +3 -3
package/dist/main.cjs
CHANGED
|
@@ -16552,6 +16552,406 @@ function getRequestAnomalyThreshold(input) {
|
|
|
16552
16552
|
return null;
|
|
16553
16553
|
}
|
|
16554
16554
|
|
|
16555
|
+
// ../../packages/shared-types/src/capture-rules.ts
|
|
16556
|
+
var CAPTURE_RULE_EVENT_TYPES = [
|
|
16557
|
+
"backend_exception",
|
|
16558
|
+
"request_event",
|
|
16559
|
+
"log_event",
|
|
16560
|
+
"frontend_breadcrumb",
|
|
16561
|
+
"frontend_exception",
|
|
16562
|
+
"deploy_metadata",
|
|
16563
|
+
"error_suppressed",
|
|
16564
|
+
"probe_event"
|
|
16565
|
+
];
|
|
16566
|
+
var CAPTURE_RULE_RUNTIME_VALUES = [
|
|
16567
|
+
"browser",
|
|
16568
|
+
"node",
|
|
16569
|
+
"python",
|
|
16570
|
+
"php",
|
|
16571
|
+
"java",
|
|
16572
|
+
"go",
|
|
16573
|
+
"ruby",
|
|
16574
|
+
"unknown"
|
|
16575
|
+
];
|
|
16576
|
+
var CaptureRuleActionValues = ["demote", "sample", "drop"];
|
|
16577
|
+
var CaptureRuleActionSchema = external_exports.enum(CaptureRuleActionValues);
|
|
16578
|
+
var CaptureRuleSampleEventClassValues = ["preserve", "context"];
|
|
16579
|
+
var CaptureRuleSampleEventClassSchema = external_exports.enum(CaptureRuleSampleEventClassValues);
|
|
16580
|
+
var CaptureRuleRuntimeSchema = external_exports.enum(CAPTURE_RULE_RUNTIME_VALUES);
|
|
16581
|
+
var CaptureRuleEventTypeSchema = external_exports.enum(CAPTURE_RULE_EVENT_TYPES);
|
|
16582
|
+
var BrowserEventKindSchema = external_exports.enum(["window_error", "resource_error"]);
|
|
16583
|
+
function normalizeOptionalTrimmedString(value) {
|
|
16584
|
+
const trimmed = value?.trim();
|
|
16585
|
+
return trimmed && trimmed.length > 0 ? trimmed : void 0;
|
|
16586
|
+
}
|
|
16587
|
+
function normalizeOptionalLowercaseHost(value) {
|
|
16588
|
+
const trimmed = normalizeOptionalTrimmedString(value);
|
|
16589
|
+
return trimmed?.toLowerCase();
|
|
16590
|
+
}
|
|
16591
|
+
function normalizeOptionalPath(value) {
|
|
16592
|
+
const trimmed = normalizeOptionalTrimmedString(value);
|
|
16593
|
+
if (trimmed === void 0) {
|
|
16594
|
+
return void 0;
|
|
16595
|
+
}
|
|
16596
|
+
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
16597
|
+
}
|
|
16598
|
+
function hasValue(value) {
|
|
16599
|
+
return value !== void 0 && value !== null;
|
|
16600
|
+
}
|
|
16601
|
+
var UrlMatcherSchema = external_exports.object({
|
|
16602
|
+
host: external_exports.string().min(1).max(255).optional(),
|
|
16603
|
+
host_suffix: external_exports.string().min(1).max(255).optional(),
|
|
16604
|
+
path_prefix: external_exports.string().min(1).max(1024).optional(),
|
|
16605
|
+
path_equals: external_exports.string().min(1).max(1024).optional()
|
|
16606
|
+
}).transform((value) => {
|
|
16607
|
+
const normalized = {};
|
|
16608
|
+
const host = normalizeOptionalLowercaseHost(value.host);
|
|
16609
|
+
const hostSuffix = normalizeOptionalLowercaseHost(value.host_suffix);
|
|
16610
|
+
const pathPrefix = normalizeOptionalPath(value.path_prefix);
|
|
16611
|
+
const pathEquals = normalizeOptionalPath(value.path_equals);
|
|
16612
|
+
if (host !== void 0) {
|
|
16613
|
+
normalized.host = host;
|
|
16614
|
+
}
|
|
16615
|
+
if (hostSuffix !== void 0) {
|
|
16616
|
+
normalized.host_suffix = hostSuffix;
|
|
16617
|
+
}
|
|
16618
|
+
if (pathPrefix !== void 0) {
|
|
16619
|
+
normalized.path_prefix = pathPrefix;
|
|
16620
|
+
}
|
|
16621
|
+
if (pathEquals !== void 0) {
|
|
16622
|
+
normalized.path_equals = pathEquals;
|
|
16623
|
+
}
|
|
16624
|
+
return normalized;
|
|
16625
|
+
}).refine((value) => hasValue(value.host) || hasValue(value.host_suffix) || hasValue(value.path_prefix) || hasValue(value.path_equals), {
|
|
16626
|
+
message: "URL matchers must include at least one host or path constraint."
|
|
16627
|
+
});
|
|
16628
|
+
var StatusRangeSchema = external_exports.object({
|
|
16629
|
+
start: external_exports.number().int().min(100).max(599),
|
|
16630
|
+
end: external_exports.number().int().min(100).max(599)
|
|
16631
|
+
}).refine((value) => value.start <= value.end, {
|
|
16632
|
+
message: "Status range start must be less than or equal to end."
|
|
16633
|
+
});
|
|
16634
|
+
var CaptureRuleFingerprintSchema = external_exports.object({
|
|
16635
|
+
version: external_exports.string().min(1).max(32),
|
|
16636
|
+
value: external_exports.string().min(1).max(256)
|
|
16637
|
+
});
|
|
16638
|
+
function normalizeStringArray(values) {
|
|
16639
|
+
if (values === void 0) {
|
|
16640
|
+
return void 0;
|
|
16641
|
+
}
|
|
16642
|
+
return Array.from(new Set(values.map((value) => value.trim()).filter((value) => value.length > 0)));
|
|
16643
|
+
}
|
|
16644
|
+
function normalizeNumberArray(values) {
|
|
16645
|
+
if (values === void 0) {
|
|
16646
|
+
return void 0;
|
|
16647
|
+
}
|
|
16648
|
+
return Array.from(new Set(values)).sort((left, right) => left - right);
|
|
16649
|
+
}
|
|
16650
|
+
var CaptureRuleMatcherSchema = external_exports.object({
|
|
16651
|
+
event_types: external_exports.array(CaptureRuleEventTypeSchema).min(1).optional(),
|
|
16652
|
+
services: external_exports.array(external_exports.string().min(1).max(120)).min(1).optional(),
|
|
16653
|
+
environments: external_exports.array(external_exports.string().min(1).max(120)).min(1).optional(),
|
|
16654
|
+
runtime: external_exports.array(CaptureRuleRuntimeSchema).min(1).optional(),
|
|
16655
|
+
first_party: external_exports.boolean().optional(),
|
|
16656
|
+
error_name: external_exports.string().min(1).max(120).optional(),
|
|
16657
|
+
message_contains: external_exports.string().min(1).max(500).optional(),
|
|
16658
|
+
message_equals: external_exports.string().min(1).max(500).optional(),
|
|
16659
|
+
browser_event_kind: BrowserEventKindSchema.optional(),
|
|
16660
|
+
resource_url: UrlMatcherSchema.optional(),
|
|
16661
|
+
request_url: UrlMatcherSchema.optional(),
|
|
16662
|
+
status_codes: external_exports.array(external_exports.number().int().min(100).max(599)).min(1).optional(),
|
|
16663
|
+
status_ranges: external_exports.array(StatusRangeSchema).min(1).optional(),
|
|
16664
|
+
fingerprint: CaptureRuleFingerprintSchema.optional()
|
|
16665
|
+
}).transform((value) => {
|
|
16666
|
+
const normalized = {};
|
|
16667
|
+
const eventTypes = normalizeStringArray(value.event_types);
|
|
16668
|
+
const services = normalizeStringArray(value.services);
|
|
16669
|
+
const environments = normalizeStringArray(value.environments);
|
|
16670
|
+
const runtime = normalizeStringArray(value.runtime);
|
|
16671
|
+
const errorName = normalizeOptionalTrimmedString(value.error_name);
|
|
16672
|
+
const messageContains = normalizeOptionalTrimmedString(value.message_contains);
|
|
16673
|
+
const messageEquals = normalizeOptionalTrimmedString(value.message_equals);
|
|
16674
|
+
const statusCodes = normalizeNumberArray(value.status_codes);
|
|
16675
|
+
if (eventTypes !== void 0) {
|
|
16676
|
+
normalized.event_types = eventTypes;
|
|
16677
|
+
}
|
|
16678
|
+
if (services !== void 0) {
|
|
16679
|
+
normalized.services = services;
|
|
16680
|
+
}
|
|
16681
|
+
if (environments !== void 0) {
|
|
16682
|
+
normalized.environments = environments;
|
|
16683
|
+
}
|
|
16684
|
+
if (runtime !== void 0) {
|
|
16685
|
+
normalized.runtime = runtime;
|
|
16686
|
+
}
|
|
16687
|
+
if (value.first_party !== void 0) {
|
|
16688
|
+
normalized.first_party = value.first_party;
|
|
16689
|
+
}
|
|
16690
|
+
if (errorName !== void 0) {
|
|
16691
|
+
normalized.error_name = errorName;
|
|
16692
|
+
}
|
|
16693
|
+
if (messageContains !== void 0) {
|
|
16694
|
+
normalized.message_contains = messageContains;
|
|
16695
|
+
}
|
|
16696
|
+
if (messageEquals !== void 0) {
|
|
16697
|
+
normalized.message_equals = messageEquals;
|
|
16698
|
+
}
|
|
16699
|
+
if (value.browser_event_kind !== void 0) {
|
|
16700
|
+
normalized.browser_event_kind = value.browser_event_kind;
|
|
16701
|
+
}
|
|
16702
|
+
if (value.resource_url !== void 0) {
|
|
16703
|
+
normalized.resource_url = value.resource_url;
|
|
16704
|
+
}
|
|
16705
|
+
if (value.request_url !== void 0) {
|
|
16706
|
+
normalized.request_url = value.request_url;
|
|
16707
|
+
}
|
|
16708
|
+
if (statusCodes !== void 0) {
|
|
16709
|
+
normalized.status_codes = statusCodes;
|
|
16710
|
+
}
|
|
16711
|
+
if (value.status_ranges !== void 0) {
|
|
16712
|
+
normalized.status_ranges = value.status_ranges;
|
|
16713
|
+
}
|
|
16714
|
+
if (value.fingerprint !== void 0) {
|
|
16715
|
+
normalized.fingerprint = value.fingerprint;
|
|
16716
|
+
}
|
|
16717
|
+
return normalized;
|
|
16718
|
+
}).superRefine((value, context) => {
|
|
16719
|
+
const narrowingKeys = [
|
|
16720
|
+
"services",
|
|
16721
|
+
"environments",
|
|
16722
|
+
"runtime",
|
|
16723
|
+
"first_party",
|
|
16724
|
+
"error_name",
|
|
16725
|
+
"message_contains",
|
|
16726
|
+
"message_equals",
|
|
16727
|
+
"browser_event_kind",
|
|
16728
|
+
"resource_url",
|
|
16729
|
+
"request_url",
|
|
16730
|
+
"status_codes",
|
|
16731
|
+
"status_ranges",
|
|
16732
|
+
"fingerprint"
|
|
16733
|
+
];
|
|
16734
|
+
if (!narrowingKeys.some((key) => hasValue(value[key]))) {
|
|
16735
|
+
context.addIssue({
|
|
16736
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16737
|
+
message: "Capture rules must include at least one narrowing field beyond event_types."
|
|
16738
|
+
});
|
|
16739
|
+
}
|
|
16740
|
+
if (value.browser_event_kind === "resource_error") {
|
|
16741
|
+
const hasResourceConstraint = hasValue(value.resource_url) || hasValue(value.fingerprint);
|
|
16742
|
+
if (!hasResourceConstraint) {
|
|
16743
|
+
context.addIssue({
|
|
16744
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16745
|
+
message: "Resource-error rules require a resource URL constraint or an exact fingerprint."
|
|
16746
|
+
});
|
|
16747
|
+
}
|
|
16748
|
+
}
|
|
16749
|
+
});
|
|
16750
|
+
var CaptureRuleCoreObjectSchema = external_exports.object({
|
|
16751
|
+
name: external_exports.string().trim().min(1).max(120),
|
|
16752
|
+
description: external_exports.string().trim().max(500).nullable(),
|
|
16753
|
+
enabled: external_exports.boolean(),
|
|
16754
|
+
action: CaptureRuleActionSchema,
|
|
16755
|
+
matcher: CaptureRuleMatcherSchema,
|
|
16756
|
+
sample_rate: external_exports.number().min(0).max(1).nullable(),
|
|
16757
|
+
sample_event_class: CaptureRuleSampleEventClassSchema.nullable(),
|
|
16758
|
+
created_by_user_id: external_exports.string().min(1).max(120).nullable(),
|
|
16759
|
+
created_from_incident_id: external_exports.string().min(1).max(120).nullable(),
|
|
16760
|
+
created_from_event_id: external_exports.string().min(1).max(120).nullable(),
|
|
16761
|
+
expires_at: external_exports.string().datetime().nullable()
|
|
16762
|
+
});
|
|
16763
|
+
function addCaptureRuleActionValidation(schema) {
|
|
16764
|
+
return schema.superRefine((value, context) => {
|
|
16765
|
+
if (value["action"] === "sample") {
|
|
16766
|
+
if (value["sample_rate"] === null) {
|
|
16767
|
+
context.addIssue({
|
|
16768
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16769
|
+
path: ["sample_rate"],
|
|
16770
|
+
message: "Sample rules require sample_rate."
|
|
16771
|
+
});
|
|
16772
|
+
}
|
|
16773
|
+
if (value["sample_event_class"] === null) {
|
|
16774
|
+
context.addIssue({
|
|
16775
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16776
|
+
path: ["sample_event_class"],
|
|
16777
|
+
message: "Sample rules require sample_event_class."
|
|
16778
|
+
});
|
|
16779
|
+
}
|
|
16780
|
+
return;
|
|
16781
|
+
}
|
|
16782
|
+
if (value["sample_rate"] !== null) {
|
|
16783
|
+
context.addIssue({
|
|
16784
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16785
|
+
path: ["sample_rate"],
|
|
16786
|
+
message: "Only sample rules can set sample_rate."
|
|
16787
|
+
});
|
|
16788
|
+
}
|
|
16789
|
+
if (value["sample_event_class"] !== null) {
|
|
16790
|
+
context.addIssue({
|
|
16791
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16792
|
+
path: ["sample_event_class"],
|
|
16793
|
+
message: "Only sample rules can set sample_event_class."
|
|
16794
|
+
});
|
|
16795
|
+
}
|
|
16796
|
+
});
|
|
16797
|
+
}
|
|
16798
|
+
var CaptureRuleSchema = addCaptureRuleActionValidation(
|
|
16799
|
+
CaptureRuleCoreObjectSchema.extend({
|
|
16800
|
+
id: external_exports.string().uuid(),
|
|
16801
|
+
project_id: external_exports.string().min(1).max(120),
|
|
16802
|
+
hit_count: external_exports.number().int().nonnegative(),
|
|
16803
|
+
last_matched_at: external_exports.string().datetime().nullable(),
|
|
16804
|
+
created_at: external_exports.string().datetime(),
|
|
16805
|
+
updated_at: external_exports.string().datetime()
|
|
16806
|
+
})
|
|
16807
|
+
);
|
|
16808
|
+
var CaptureRuleCreateSchema = external_exports.object({
|
|
16809
|
+
name: external_exports.string().trim().min(1).max(120),
|
|
16810
|
+
description: external_exports.string().trim().max(500).nullable().default(null),
|
|
16811
|
+
enabled: external_exports.boolean().default(true),
|
|
16812
|
+
action: CaptureRuleActionSchema,
|
|
16813
|
+
matcher: CaptureRuleMatcherSchema,
|
|
16814
|
+
sample_rate: external_exports.number().min(0).max(1).nullable().optional(),
|
|
16815
|
+
sample_event_class: CaptureRuleSampleEventClassSchema.nullable().optional(),
|
|
16816
|
+
created_by_user_id: external_exports.string().min(1).max(120).nullable().default(null),
|
|
16817
|
+
created_from_incident_id: external_exports.string().min(1).max(120).nullable().default(null),
|
|
16818
|
+
created_from_event_id: external_exports.string().min(1).max(120).nullable().default(null),
|
|
16819
|
+
expires_at: external_exports.string().datetime().nullable().default(null)
|
|
16820
|
+
}).superRefine((value, context) => {
|
|
16821
|
+
if (value.action === "sample") {
|
|
16822
|
+
if (value.sample_rate === void 0 || value.sample_rate === null) {
|
|
16823
|
+
context.addIssue({
|
|
16824
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16825
|
+
path: ["sample_rate"],
|
|
16826
|
+
message: "Sample rules require sample_rate."
|
|
16827
|
+
});
|
|
16828
|
+
}
|
|
16829
|
+
return;
|
|
16830
|
+
}
|
|
16831
|
+
if (value.sample_rate !== void 0 && value.sample_rate !== null) {
|
|
16832
|
+
context.addIssue({
|
|
16833
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16834
|
+
path: ["sample_rate"],
|
|
16835
|
+
message: "Only sample rules can set sample_rate."
|
|
16836
|
+
});
|
|
16837
|
+
}
|
|
16838
|
+
if (value.sample_event_class !== void 0 && value.sample_event_class !== null) {
|
|
16839
|
+
context.addIssue({
|
|
16840
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16841
|
+
path: ["sample_event_class"],
|
|
16842
|
+
message: "Only sample rules can set sample_event_class."
|
|
16843
|
+
});
|
|
16844
|
+
}
|
|
16845
|
+
}).transform((value) => ({
|
|
16846
|
+
...value,
|
|
16847
|
+
sample_rate: value.action === "sample" ? value.sample_rate : null,
|
|
16848
|
+
sample_event_class: value.action === "sample" ? value.sample_event_class ?? "preserve" : null
|
|
16849
|
+
}));
|
|
16850
|
+
var CaptureRuleUpdateSchema = external_exports.object({
|
|
16851
|
+
name: external_exports.string().trim().min(1).max(120).optional(),
|
|
16852
|
+
description: external_exports.string().trim().max(500).nullable().optional(),
|
|
16853
|
+
enabled: external_exports.boolean().optional(),
|
|
16854
|
+
action: CaptureRuleActionSchema.optional(),
|
|
16855
|
+
matcher: CaptureRuleMatcherSchema.optional(),
|
|
16856
|
+
sample_rate: external_exports.number().min(0).max(1).nullable().optional(),
|
|
16857
|
+
sample_event_class: CaptureRuleSampleEventClassSchema.nullable().optional(),
|
|
16858
|
+
expires_at: external_exports.string().datetime().nullable().optional()
|
|
16859
|
+
}).superRefine((value, context) => {
|
|
16860
|
+
if (Object.keys(value).length === 0) {
|
|
16861
|
+
context.addIssue({
|
|
16862
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16863
|
+
message: "At least one capture rule field must be provided."
|
|
16864
|
+
});
|
|
16865
|
+
}
|
|
16866
|
+
const resolvedAction = value.action;
|
|
16867
|
+
if (resolvedAction === "sample") {
|
|
16868
|
+
if (!("sample_rate" in value)) {
|
|
16869
|
+
context.addIssue({
|
|
16870
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16871
|
+
path: ["sample_rate"],
|
|
16872
|
+
message: "Sample rule updates must include sample_rate when changing action to sample."
|
|
16873
|
+
});
|
|
16874
|
+
}
|
|
16875
|
+
if (!("sample_event_class" in value)) {
|
|
16876
|
+
context.addIssue({
|
|
16877
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16878
|
+
path: ["sample_event_class"],
|
|
16879
|
+
message: "Sample rule updates must include sample_event_class when changing action to sample."
|
|
16880
|
+
});
|
|
16881
|
+
}
|
|
16882
|
+
return;
|
|
16883
|
+
}
|
|
16884
|
+
if ("sample_rate" in value) {
|
|
16885
|
+
context.addIssue({
|
|
16886
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16887
|
+
path: ["sample_rate"],
|
|
16888
|
+
message: "Sample rule fields can only be updated while setting action to sample."
|
|
16889
|
+
});
|
|
16890
|
+
}
|
|
16891
|
+
if ("sample_event_class" in value) {
|
|
16892
|
+
context.addIssue({
|
|
16893
|
+
code: external_exports.ZodIssueCode.custom,
|
|
16894
|
+
path: ["sample_event_class"],
|
|
16895
|
+
message: "Sample rule fields can only be updated while setting action to sample."
|
|
16896
|
+
});
|
|
16897
|
+
}
|
|
16898
|
+
});
|
|
16899
|
+
var CaptureRuleResponseSchema = external_exports.object({
|
|
16900
|
+
rule: CaptureRuleSchema
|
|
16901
|
+
});
|
|
16902
|
+
var CaptureRulesResponseSchema = external_exports.object({
|
|
16903
|
+
access_mode: external_exports.enum(["manage", "preview"]),
|
|
16904
|
+
rules: external_exports.array(CaptureRuleSchema)
|
|
16905
|
+
});
|
|
16906
|
+
var CaptureRulesFileSchema = external_exports.object({
|
|
16907
|
+
version: external_exports.literal(1),
|
|
16908
|
+
rules: external_exports.array(CaptureRuleSchema)
|
|
16909
|
+
});
|
|
16910
|
+
var CaptureRuleEvaluationUrlSchema = external_exports.object({
|
|
16911
|
+
host: external_exports.string().min(1).transform((value) => value.toLowerCase()).optional(),
|
|
16912
|
+
path: external_exports.string().min(1).transform((value) => value.startsWith("/") ? value : `/${value}`)
|
|
16913
|
+
});
|
|
16914
|
+
var CaptureRuleEvaluationContextSchema = external_exports.object({
|
|
16915
|
+
project_id: external_exports.string().min(1).max(120),
|
|
16916
|
+
event_id: external_exports.string().uuid(),
|
|
16917
|
+
event_type: CaptureRuleEventTypeSchema,
|
|
16918
|
+
service: external_exports.string().min(1).optional(),
|
|
16919
|
+
environment: external_exports.string().min(1).optional(),
|
|
16920
|
+
runtime: CaptureRuleRuntimeSchema,
|
|
16921
|
+
first_party: external_exports.boolean().optional(),
|
|
16922
|
+
error_name: external_exports.string().min(1).optional(),
|
|
16923
|
+
message: external_exports.string().min(1).optional(),
|
|
16924
|
+
browser_event_kind: BrowserEventKindSchema.optional(),
|
|
16925
|
+
resource_url: CaptureRuleEvaluationUrlSchema.optional(),
|
|
16926
|
+
request_url: CaptureRuleEvaluationUrlSchema.optional(),
|
|
16927
|
+
status_code: external_exports.number().int().min(0).max(599).optional(),
|
|
16928
|
+
fingerprint: CaptureRuleFingerprintSchema.optional()
|
|
16929
|
+
});
|
|
16930
|
+
|
|
16931
|
+
// ../../packages/shared-types/src/capture-rule-suggestions.ts
|
|
16932
|
+
var CaptureRuleSuggestionConfidenceSchema = external_exports.enum(["high", "medium", "low"]);
|
|
16933
|
+
var CaptureRuleSuggestionSchema = external_exports.object({
|
|
16934
|
+
suggestion_id: external_exports.string().min(1).max(120),
|
|
16935
|
+
label: external_exports.string().min(1).max(200),
|
|
16936
|
+
recommended_action: CaptureRuleActionSchema,
|
|
16937
|
+
confidence: CaptureRuleSuggestionConfidenceSchema,
|
|
16938
|
+
reason: external_exports.string().min(1).max(500),
|
|
16939
|
+
requires_confirmation: external_exports.boolean(),
|
|
16940
|
+
rule: CaptureRuleCreateSchema
|
|
16941
|
+
});
|
|
16942
|
+
var CaptureRuleSuggestionsResponseSchema = external_exports.object({
|
|
16943
|
+
suggestions: external_exports.array(CaptureRuleSuggestionSchema),
|
|
16944
|
+
bundle_status: external_exports.enum(["ready", "pending", "failed"]).optional(),
|
|
16945
|
+
bundle_reason: external_exports.string().nullable().optional()
|
|
16946
|
+
});
|
|
16947
|
+
var CreateCaptureRuleFromSuggestionSchema = external_exports.object({
|
|
16948
|
+
suggestion_id: external_exports.string().min(1).max(120),
|
|
16949
|
+
name: external_exports.string().trim().min(1).max(120).optional(),
|
|
16950
|
+
description: external_exports.string().trim().max(500).nullable().optional(),
|
|
16951
|
+
enabled: external_exports.boolean().optional(),
|
|
16952
|
+
expires_at: external_exports.string().datetime().nullable().optional()
|
|
16953
|
+
});
|
|
16954
|
+
|
|
16555
16955
|
// ../../packages/shared-types/src/improvement-settings.ts
|
|
16556
16956
|
var ImprovementBundleSensitivityValues = [
|
|
16557
16957
|
"high_confidence",
|
|
@@ -16708,6 +17108,18 @@ var DeviceInfoSchema = external_exports.object({
|
|
|
16708
17108
|
connection_type: external_exports.string().nullable(),
|
|
16709
17109
|
color_scheme_preference: external_exports.enum(["light", "dark", "no-preference"]).nullable()
|
|
16710
17110
|
}).strict();
|
|
17111
|
+
var BrowserExceptionEventSchema = external_exports.object({
|
|
17112
|
+
kind: external_exports.enum(["window_error", "resource_error"]),
|
|
17113
|
+
message: external_exports.string().nullable(),
|
|
17114
|
+
file_name: external_exports.string().nullable(),
|
|
17115
|
+
line_number: external_exports.number().int().nonnegative().nullable(),
|
|
17116
|
+
column_number: external_exports.number().int().nonnegative().nullable(),
|
|
17117
|
+
target: external_exports.object({
|
|
17118
|
+
tag_name: external_exports.string().nullable(),
|
|
17119
|
+
source_url: external_exports.string().nullable()
|
|
17120
|
+
}).nullable(),
|
|
17121
|
+
opaque: external_exports.boolean()
|
|
17122
|
+
}).strict();
|
|
16711
17123
|
var FrontendExceptionPayloadSchema = external_exports.object({
|
|
16712
17124
|
name: external_exports.string().min(1),
|
|
16713
17125
|
message: external_exports.string().min(1),
|
|
@@ -16719,6 +17131,7 @@ var FrontendExceptionPayloadSchema = external_exports.object({
|
|
|
16719
17131
|
}),
|
|
16720
17132
|
breadcrumbs: external_exports.array(FrontendExceptionBreadcrumbSchema).optional(),
|
|
16721
17133
|
device: DeviceInfoSchema.nullable().optional(),
|
|
17134
|
+
browser_event: BrowserExceptionEventSchema.optional(),
|
|
16722
17135
|
dom_context: external_exports.object({
|
|
16723
17136
|
mode: external_exports.literal("lightweight"),
|
|
16724
17137
|
html_excerpt: external_exports.string().min(1)
|
|
@@ -17175,6 +17588,18 @@ function buildSkill() {
|
|
|
17175
17588
|
"- Run `debugbundle validate --fix` to restore missing generated setup files without overwriting the profile.",
|
|
17176
17589
|
"- Run `debugbundle process` after local events land in `.debugbundle/local/events/`.",
|
|
17177
17590
|
"",
|
|
17591
|
+
"## Browser Capture and Relay Setup",
|
|
17592
|
+
"",
|
|
17593
|
+
"When the repository has a browser frontend, verify capture end to end instead of stopping at backend SDK setup.",
|
|
17594
|
+
"",
|
|
17595
|
+
"1. Add `@debugbundle/sdk-browser` to each browser app that should capture console, error, navigation, or request context.",
|
|
17596
|
+
"2. Initialize the browser SDK from the app entrypoint with the active environment and a browser relay endpoint.",
|
|
17597
|
+
"3. Add a backend relay endpoint at `/debugbundle/browser` using the server SDK relay helper when available.",
|
|
17598
|
+
"4. For same-origin apps, keep the browser endpoint as `/debugbundle/browser`.",
|
|
17599
|
+
"5. For split frontend/backend hosts, configure the browser endpoint to the API host relay URL and require explicit frontend origin allowlisting on the backend.",
|
|
17600
|
+
"6. Ensure auth and CSRF middleware allow the relay path while the relay still enforces origin, content type, body size, schema validation, and rate limits.",
|
|
17601
|
+
"7. Trigger a local browser smoke event, then run `debugbundle process --json` and confirm the incident or context event appears before marking setup complete.",
|
|
17602
|
+
"",
|
|
17178
17603
|
"## References",
|
|
17179
17604
|
"",
|
|
17180
17605
|
"- CLI reference: `references/cli.md`",
|
|
@@ -17311,6 +17736,8 @@ function buildProfileEnrichmentReference() {
|
|
|
17311
17736
|
"- add critical paths for ingestion, processing, retrieval, SDK capture, auth, billing, and any project-specific high-risk workflows",
|
|
17312
17737
|
"- confirm `repo.generated_paths` and `repo.do_not_edit_paths` match the local scaffold",
|
|
17313
17738
|
"- confirm build, test, lint, and install workflows in `developer_workflows`",
|
|
17739
|
+
"- for browser frontends, confirm `@debugbundle/sdk-browser` is initialized and a backend `/debugbundle/browser` relay is reachable",
|
|
17740
|
+
"- for split frontend/backend hosts, confirm the browser SDK uses the API relay URL and the backend allowlists the frontend origin",
|
|
17314
17741
|
"- update `debugbundle.last_reviewed_at` and set `debugbundle.validation_status` to `agent-validated` when complete",
|
|
17315
17742
|
""
|
|
17316
17743
|
].join("\n");
|
|
@@ -17504,10 +17931,37 @@ async function pathExists(path, stat) {
|
|
|
17504
17931
|
}
|
|
17505
17932
|
}
|
|
17506
17933
|
function formatZodErrors(error) {
|
|
17507
|
-
return error.issues.map((issue) =>
|
|
17508
|
-
path
|
|
17509
|
-
|
|
17510
|
-
|
|
17934
|
+
return error.issues.map((issue) => {
|
|
17935
|
+
const path = issue.path.join(".");
|
|
17936
|
+
if (path === "services" || path.startsWith("services.")) {
|
|
17937
|
+
return {
|
|
17938
|
+
path,
|
|
17939
|
+
message: issue.message,
|
|
17940
|
+
suggestion: "Add service entries with name, kind, runtime, framework, paths, owns_routes, and depends_on.",
|
|
17941
|
+
example: '[{"name":"api","kind":"backend","runtime":"Node.js","framework":"Fastify","paths":["apps/api"],"owns_routes":["POST /checkout"],"depends_on":["worker"]}]'
|
|
17942
|
+
};
|
|
17943
|
+
}
|
|
17944
|
+
if (path === "critical_paths" || path.startsWith("critical_paths.")) {
|
|
17945
|
+
return {
|
|
17946
|
+
path,
|
|
17947
|
+
message: issue.message,
|
|
17948
|
+
suggestion: "Use object entries so each critical path records its owner_service and review notes.",
|
|
17949
|
+
example: '[{"name":"checkout","owner_service":"api","notes":"Creates the order, charges the card, and enqueues fulfillment."}]'
|
|
17950
|
+
};
|
|
17951
|
+
}
|
|
17952
|
+
if (path === "developer_workflows" || path.startsWith("developer_workflows.")) {
|
|
17953
|
+
return {
|
|
17954
|
+
path,
|
|
17955
|
+
message: issue.message,
|
|
17956
|
+
suggestion: "Provide install, build, test, and lint as command strings so agents can run the standard repo workflows.",
|
|
17957
|
+
example: '{"install":"pnpm install","build":"pnpm build","test":"pnpm test","lint":"pnpm lint"}'
|
|
17958
|
+
};
|
|
17959
|
+
}
|
|
17960
|
+
return {
|
|
17961
|
+
path,
|
|
17962
|
+
message: issue.message
|
|
17963
|
+
};
|
|
17964
|
+
});
|
|
17511
17965
|
}
|
|
17512
17966
|
async function validateProfile(rootDirectory, dependencies = {}) {
|
|
17513
17967
|
const readFile = dependencies.readFile ?? ((filePath) => (0, import_promises.readFile)(filePath, "utf8"));
|
|
@@ -17854,6 +18308,118 @@ function createCliHttpClient(input, dependencies) {
|
|
|
17854
18308
|
};
|
|
17855
18309
|
}
|
|
17856
18310
|
|
|
18311
|
+
// ../cli/src/capture-rule-commands.ts
|
|
18312
|
+
var CaptureRuleApiError = class extends Error {
|
|
18313
|
+
status;
|
|
18314
|
+
constructor(status, message) {
|
|
18315
|
+
super(message);
|
|
18316
|
+
this.name = "CaptureRuleApiError";
|
|
18317
|
+
this.status = status;
|
|
18318
|
+
}
|
|
18319
|
+
};
|
|
18320
|
+
function toApiError(status, body, fallback) {
|
|
18321
|
+
if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
|
|
18322
|
+
return new CaptureRuleApiError(status, body.error);
|
|
18323
|
+
}
|
|
18324
|
+
return new CaptureRuleApiError(status, fallback);
|
|
18325
|
+
}
|
|
18326
|
+
function createCaptureRuleApi(httpClient) {
|
|
18327
|
+
return {
|
|
18328
|
+
async listCaptureRules(input) {
|
|
18329
|
+
const response = await httpClient.request({
|
|
18330
|
+
method: "GET",
|
|
18331
|
+
path: `/v1/projects/${encodeURIComponent(input.projectId)}/capture-rules`,
|
|
18332
|
+
bearerToken: input.bearerToken
|
|
18333
|
+
});
|
|
18334
|
+
if (response.status !== 200) {
|
|
18335
|
+
throw toApiError(response.status, response.body, "Failed to list capture rules.");
|
|
18336
|
+
}
|
|
18337
|
+
const parsed = CaptureRulesResponseSchema.safeParse(response.body);
|
|
18338
|
+
if (!parsed.success) {
|
|
18339
|
+
throw new CaptureRuleApiError(500, "Invalid capture rule list response.");
|
|
18340
|
+
}
|
|
18341
|
+
return parsed.data;
|
|
18342
|
+
},
|
|
18343
|
+
async createCaptureRule(input) {
|
|
18344
|
+
const response = await httpClient.request({
|
|
18345
|
+
method: "POST",
|
|
18346
|
+
path: `/v1/projects/${encodeURIComponent(input.projectId)}/capture-rules`,
|
|
18347
|
+
bearerToken: input.bearerToken,
|
|
18348
|
+
body: input.create
|
|
18349
|
+
});
|
|
18350
|
+
if (response.status !== 201) {
|
|
18351
|
+
throw toApiError(response.status, response.body, "Failed to create capture rule.");
|
|
18352
|
+
}
|
|
18353
|
+
const parsed = CaptureRuleResponseSchema.safeParse(response.body);
|
|
18354
|
+
if (!parsed.success) {
|
|
18355
|
+
throw new CaptureRuleApiError(500, "Invalid capture rule create response.");
|
|
18356
|
+
}
|
|
18357
|
+
return parsed.data;
|
|
18358
|
+
},
|
|
18359
|
+
async suggestCaptureRulesFromIncident(input) {
|
|
18360
|
+
const response = await httpClient.request({
|
|
18361
|
+
method: "POST",
|
|
18362
|
+
path: `/v1/incidents/${encodeURIComponent(input.incidentId)}/capture-rule-suggestion`,
|
|
18363
|
+
bearerToken: input.bearerToken
|
|
18364
|
+
});
|
|
18365
|
+
if (response.status !== 200) {
|
|
18366
|
+
throw toApiError(response.status, response.body, "Failed to suggest capture rules.");
|
|
18367
|
+
}
|
|
18368
|
+
const parsed = CaptureRuleSuggestionsResponseSchema.safeParse(response.body);
|
|
18369
|
+
if (!parsed.success) {
|
|
18370
|
+
throw new CaptureRuleApiError(500, "Invalid capture rule suggestion response.");
|
|
18371
|
+
}
|
|
18372
|
+
return parsed.data;
|
|
18373
|
+
},
|
|
18374
|
+
async createCaptureRuleFromIncidentSuggestion(input) {
|
|
18375
|
+
const response = await httpClient.request({
|
|
18376
|
+
method: "POST",
|
|
18377
|
+
path: `/v1/incidents/${encodeURIComponent(input.incidentId)}/capture-rules`,
|
|
18378
|
+
bearerToken: input.bearerToken,
|
|
18379
|
+
body: input.create
|
|
18380
|
+
});
|
|
18381
|
+
if (response.status !== 201) {
|
|
18382
|
+
throw toApiError(response.status, response.body, "Failed to create capture rule from suggestion.");
|
|
18383
|
+
}
|
|
18384
|
+
const parsed = CaptureRuleResponseSchema.safeParse(response.body);
|
|
18385
|
+
if (!parsed.success) {
|
|
18386
|
+
throw new CaptureRuleApiError(500, "Invalid capture rule create-from-suggestion response.");
|
|
18387
|
+
}
|
|
18388
|
+
return parsed.data;
|
|
18389
|
+
},
|
|
18390
|
+
async updateCaptureRule(input) {
|
|
18391
|
+
const response = await httpClient.request({
|
|
18392
|
+
method: "PATCH",
|
|
18393
|
+
path: `/v1/projects/${encodeURIComponent(input.projectId)}/capture-rules/${encodeURIComponent(input.ruleId)}`,
|
|
18394
|
+
bearerToken: input.bearerToken,
|
|
18395
|
+
body: input.update
|
|
18396
|
+
});
|
|
18397
|
+
if (response.status !== 200) {
|
|
18398
|
+
throw toApiError(response.status, response.body, "Failed to update capture rule.");
|
|
18399
|
+
}
|
|
18400
|
+
const parsed = CaptureRuleResponseSchema.safeParse(response.body);
|
|
18401
|
+
if (!parsed.success) {
|
|
18402
|
+
throw new CaptureRuleApiError(500, "Invalid capture rule update response.");
|
|
18403
|
+
}
|
|
18404
|
+
return parsed.data;
|
|
18405
|
+
},
|
|
18406
|
+
async deleteCaptureRule(input) {
|
|
18407
|
+
const response = await httpClient.request({
|
|
18408
|
+
method: "DELETE",
|
|
18409
|
+
path: `/v1/projects/${encodeURIComponent(input.projectId)}/capture-rules/${encodeURIComponent(input.ruleId)}`,
|
|
18410
|
+
bearerToken: input.bearerToken
|
|
18411
|
+
});
|
|
18412
|
+
if (response.status !== 200) {
|
|
18413
|
+
throw toApiError(response.status, response.body, "Failed to delete capture rule.");
|
|
18414
|
+
}
|
|
18415
|
+
if (typeof response.body !== "object" || response.body === null || !("success" in response.body) || response.body.success !== true) {
|
|
18416
|
+
throw new CaptureRuleApiError(500, "Invalid capture rule delete response.");
|
|
18417
|
+
}
|
|
18418
|
+
return { success: true };
|
|
18419
|
+
}
|
|
18420
|
+
};
|
|
18421
|
+
}
|
|
18422
|
+
|
|
17857
18423
|
// ../cli/src/capture-policy-commands.ts
|
|
17858
18424
|
var CapturePolicyApiError = class extends Error {
|
|
17859
18425
|
status;
|
|
@@ -17863,7 +18429,7 @@ var CapturePolicyApiError = class extends Error {
|
|
|
17863
18429
|
this.status = status;
|
|
17864
18430
|
}
|
|
17865
18431
|
};
|
|
17866
|
-
function
|
|
18432
|
+
function toApiError2(status, body, fallback) {
|
|
17867
18433
|
if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
|
|
17868
18434
|
return new CapturePolicyApiError(status, body.error);
|
|
17869
18435
|
}
|
|
@@ -17878,7 +18444,7 @@ function createCapturePolicyApi(httpClient) {
|
|
|
17878
18444
|
bearerToken: input.bearerToken
|
|
17879
18445
|
});
|
|
17880
18446
|
if (response.status !== 200) {
|
|
17881
|
-
throw
|
|
18447
|
+
throw toApiError2(response.status, response.body, "Failed to get capture policy.");
|
|
17882
18448
|
}
|
|
17883
18449
|
const parsed = CapturePolicyResponseSchema.safeParse(response.body);
|
|
17884
18450
|
if (!parsed.success) {
|
|
@@ -17894,7 +18460,7 @@ function createCapturePolicyApi(httpClient) {
|
|
|
17894
18460
|
body: input.update
|
|
17895
18461
|
});
|
|
17896
18462
|
if (response.status !== 200) {
|
|
17897
|
-
throw
|
|
18463
|
+
throw toApiError2(response.status, response.body, "Failed to update capture policy.");
|
|
17898
18464
|
}
|
|
17899
18465
|
const parsed = CapturePolicyResponseSchema.safeParse(response.body);
|
|
17900
18466
|
if (!parsed.success) {
|
|
@@ -17914,7 +18480,7 @@ var ImprovementSettingsApiError = class extends Error {
|
|
|
17914
18480
|
this.status = status;
|
|
17915
18481
|
}
|
|
17916
18482
|
};
|
|
17917
|
-
function
|
|
18483
|
+
function toApiError3(status, body, fallback) {
|
|
17918
18484
|
if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
|
|
17919
18485
|
return new ImprovementSettingsApiError(status, body.error);
|
|
17920
18486
|
}
|
|
@@ -17929,7 +18495,7 @@ function createImprovementSettingsApi(httpClient) {
|
|
|
17929
18495
|
bearerToken: input.bearerToken
|
|
17930
18496
|
});
|
|
17931
18497
|
if (response.status !== 200) {
|
|
17932
|
-
throw
|
|
18498
|
+
throw toApiError3(response.status, response.body, "Failed to get improvement settings.");
|
|
17933
18499
|
}
|
|
17934
18500
|
const parsed = ImprovementSettingsResponseSchema.safeParse(response.body);
|
|
17935
18501
|
if (!parsed.success) {
|
|
@@ -17945,7 +18511,7 @@ function createImprovementSettingsApi(httpClient) {
|
|
|
17945
18511
|
body: input.update
|
|
17946
18512
|
});
|
|
17947
18513
|
if (response.status !== 200) {
|
|
17948
|
-
throw
|
|
18514
|
+
throw toApiError3(response.status, response.body, "Failed to update improvement settings.");
|
|
17949
18515
|
}
|
|
17950
18516
|
const parsed = ImprovementSettingsResponseSchema.safeParse(response.body);
|
|
17951
18517
|
if (!parsed.success) {
|
|
@@ -17967,7 +18533,7 @@ var MemberApiError = class extends Error {
|
|
|
17967
18533
|
this.code = code;
|
|
17968
18534
|
}
|
|
17969
18535
|
};
|
|
17970
|
-
function
|
|
18536
|
+
function toApiError4(status, body) {
|
|
17971
18537
|
if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
|
|
17972
18538
|
return new MemberApiError(status, body.error);
|
|
17973
18539
|
}
|
|
@@ -17982,7 +18548,7 @@ function createMemberApi(httpClient) {
|
|
|
17982
18548
|
bearerToken: input.bearerToken
|
|
17983
18549
|
});
|
|
17984
18550
|
if (response.status !== 200) {
|
|
17985
|
-
throw
|
|
18551
|
+
throw toApiError4(response.status, response.body);
|
|
17986
18552
|
}
|
|
17987
18553
|
return response.body;
|
|
17988
18554
|
},
|
|
@@ -17993,7 +18559,7 @@ function createMemberApi(httpClient) {
|
|
|
17993
18559
|
bearerToken: input.bearerToken
|
|
17994
18560
|
});
|
|
17995
18561
|
if (response.status !== 200) {
|
|
17996
|
-
throw
|
|
18562
|
+
throw toApiError4(response.status, response.body);
|
|
17997
18563
|
}
|
|
17998
18564
|
return response.body;
|
|
17999
18565
|
},
|
|
@@ -18005,7 +18571,7 @@ function createMemberApi(httpClient) {
|
|
|
18005
18571
|
body: { email: input.email, role: input.role }
|
|
18006
18572
|
});
|
|
18007
18573
|
if (response.status !== 201) {
|
|
18008
|
-
throw
|
|
18574
|
+
throw toApiError4(response.status, response.body);
|
|
18009
18575
|
}
|
|
18010
18576
|
return response.body;
|
|
18011
18577
|
},
|
|
@@ -18016,7 +18582,7 @@ function createMemberApi(httpClient) {
|
|
|
18016
18582
|
bearerToken: input.bearerToken
|
|
18017
18583
|
});
|
|
18018
18584
|
if (response.status !== 200) {
|
|
18019
|
-
throw
|
|
18585
|
+
throw toApiError4(response.status, response.body);
|
|
18020
18586
|
}
|
|
18021
18587
|
return response.body;
|
|
18022
18588
|
},
|
|
@@ -18028,7 +18594,7 @@ function createMemberApi(httpClient) {
|
|
|
18028
18594
|
body: { role: input.role }
|
|
18029
18595
|
});
|
|
18030
18596
|
if (response.status !== 200) {
|
|
18031
|
-
throw
|
|
18597
|
+
throw toApiError4(response.status, response.body);
|
|
18032
18598
|
}
|
|
18033
18599
|
return response.body;
|
|
18034
18600
|
},
|
|
@@ -18039,7 +18605,7 @@ function createMemberApi(httpClient) {
|
|
|
18039
18605
|
bearerToken: input.bearerToken
|
|
18040
18606
|
});
|
|
18041
18607
|
if (response.status !== 200) {
|
|
18042
|
-
throw
|
|
18608
|
+
throw toApiError4(response.status, response.body);
|
|
18043
18609
|
}
|
|
18044
18610
|
return response.body;
|
|
18045
18611
|
}
|
|
@@ -18057,7 +18623,7 @@ var ProbeApiError = class extends Error {
|
|
|
18057
18623
|
this.code = code;
|
|
18058
18624
|
}
|
|
18059
18625
|
};
|
|
18060
|
-
function
|
|
18626
|
+
function toApiError5(status, body) {
|
|
18061
18627
|
if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
|
|
18062
18628
|
return new ProbeApiError(status, body.error);
|
|
18063
18629
|
}
|
|
@@ -18088,7 +18654,7 @@ function createProbeApi(httpClient) {
|
|
|
18088
18654
|
body
|
|
18089
18655
|
});
|
|
18090
18656
|
if (response.status !== 201) {
|
|
18091
|
-
throw
|
|
18657
|
+
throw toApiError5(response.status, response.body);
|
|
18092
18658
|
}
|
|
18093
18659
|
return response.body;
|
|
18094
18660
|
},
|
|
@@ -18099,7 +18665,7 @@ function createProbeApi(httpClient) {
|
|
|
18099
18665
|
bearerToken: input.bearerToken
|
|
18100
18666
|
});
|
|
18101
18667
|
if (response.status !== 200) {
|
|
18102
|
-
throw
|
|
18668
|
+
throw toApiError5(response.status, response.body);
|
|
18103
18669
|
}
|
|
18104
18670
|
return response.body;
|
|
18105
18671
|
},
|
|
@@ -18111,7 +18677,7 @@ function createProbeApi(httpClient) {
|
|
|
18111
18677
|
body: { activation_id: input.activationId }
|
|
18112
18678
|
});
|
|
18113
18679
|
if (response.status !== 200) {
|
|
18114
|
-
throw
|
|
18680
|
+
throw toApiError5(response.status, response.body);
|
|
18115
18681
|
}
|
|
18116
18682
|
return response.body;
|
|
18117
18683
|
}
|
|
@@ -18234,6 +18800,15 @@ function inferMatchedFields(event) {
|
|
|
18234
18800
|
if (event.top_frames.length > 0) {
|
|
18235
18801
|
matchedFields.push("top_frames");
|
|
18236
18802
|
}
|
|
18803
|
+
if (event.browser_event_kind != null) {
|
|
18804
|
+
matchedFields.push("browser_event_kind");
|
|
18805
|
+
}
|
|
18806
|
+
if (event.resource_host != null) {
|
|
18807
|
+
matchedFields.push("resource_host");
|
|
18808
|
+
}
|
|
18809
|
+
if (event.resource_path != null) {
|
|
18810
|
+
matchedFields.push("resource_path");
|
|
18811
|
+
}
|
|
18237
18812
|
if (event.http_method !== null) {
|
|
18238
18813
|
matchedFields.push("http_method");
|
|
18239
18814
|
}
|
|
@@ -18294,6 +18869,39 @@ function selectTopFrames(stack, limit = 5) {
|
|
|
18294
18869
|
const frames = normalizedStack.split("\n").map((line) => line.trim()).filter((line) => line.startsWith("at ")).filter((line) => FRAME_NOISE_PATTERNS.every((pattern) => !line.includes(pattern))).slice(0, limit);
|
|
18295
18870
|
return frames;
|
|
18296
18871
|
}
|
|
18872
|
+
function normalizeResourceIdentity(value) {
|
|
18873
|
+
if (value === null) {
|
|
18874
|
+
return { host: null, path: null };
|
|
18875
|
+
}
|
|
18876
|
+
const trimmed = value.trim();
|
|
18877
|
+
if (trimmed.length === 0) {
|
|
18878
|
+
return { host: null, path: null };
|
|
18879
|
+
}
|
|
18880
|
+
if (trimmed.startsWith("/")) {
|
|
18881
|
+
return {
|
|
18882
|
+
host: null,
|
|
18883
|
+
path: normalizeRoute(trimmed)
|
|
18884
|
+
};
|
|
18885
|
+
}
|
|
18886
|
+
try {
|
|
18887
|
+
const parsed = new URL(trimmed);
|
|
18888
|
+
if (parsed.protocol === "http:" || parsed.protocol === "https:") {
|
|
18889
|
+
return {
|
|
18890
|
+
host: parsed.hostname.length > 0 ? parsed.hostname.toLowerCase() : null,
|
|
18891
|
+
path: normalizeRoute(parsed.pathname)
|
|
18892
|
+
};
|
|
18893
|
+
}
|
|
18894
|
+
return {
|
|
18895
|
+
host: null,
|
|
18896
|
+
path: parsed.protocol.replace(/:$/, "")
|
|
18897
|
+
};
|
|
18898
|
+
} catch {
|
|
18899
|
+
return {
|
|
18900
|
+
host: null,
|
|
18901
|
+
path: normalizeRoute(trimmed) ?? trimmed
|
|
18902
|
+
};
|
|
18903
|
+
}
|
|
18904
|
+
}
|
|
18297
18905
|
function stableJson(value) {
|
|
18298
18906
|
if (value === null || typeof value !== "object") {
|
|
18299
18907
|
return JSON.stringify(value);
|
|
@@ -18321,6 +18929,9 @@ function normalizeEvent(event) {
|
|
|
18321
18929
|
http_method: event.payload.request.method,
|
|
18322
18930
|
http_status: event.payload.response.status_code,
|
|
18323
18931
|
top_frames: selectTopFrames(event.payload.stack),
|
|
18932
|
+
browser_event_kind: null,
|
|
18933
|
+
resource_host: null,
|
|
18934
|
+
resource_path: null,
|
|
18324
18935
|
payload: redactedPayload
|
|
18325
18936
|
};
|
|
18326
18937
|
}
|
|
@@ -18334,6 +18945,9 @@ function normalizeEvent(event) {
|
|
|
18334
18945
|
http_method: event.payload.method,
|
|
18335
18946
|
http_status: event.payload.response_status,
|
|
18336
18947
|
top_frames: [],
|
|
18948
|
+
browser_event_kind: null,
|
|
18949
|
+
resource_host: null,
|
|
18950
|
+
resource_path: null,
|
|
18337
18951
|
payload: redactedPayload
|
|
18338
18952
|
};
|
|
18339
18953
|
}
|
|
@@ -18347,6 +18961,28 @@ function normalizeEvent(event) {
|
|
|
18347
18961
|
http_method: null,
|
|
18348
18962
|
http_status: null,
|
|
18349
18963
|
top_frames: [],
|
|
18964
|
+
browser_event_kind: null,
|
|
18965
|
+
resource_host: null,
|
|
18966
|
+
resource_path: null,
|
|
18967
|
+
payload: redactedPayload
|
|
18968
|
+
};
|
|
18969
|
+
}
|
|
18970
|
+
if (event.event_type === "frontend_exception") {
|
|
18971
|
+
const browserEvent = event.payload.browser_event;
|
|
18972
|
+
const resourceIdentity = browserEvent?.kind === "resource_error" ? normalizeResourceIdentity(browserEvent.target?.source_url ?? browserEvent.file_name) : { host: null, path: null };
|
|
18973
|
+
const topFrames = browserEvent?.opaque === true ? [] : selectTopFrames(event.payload.stack);
|
|
18974
|
+
return {
|
|
18975
|
+
event_type: event.event_type,
|
|
18976
|
+
environment: event.service.environment,
|
|
18977
|
+
error_type: event.payload.name,
|
|
18978
|
+
normalized_message: normalizeMessage(event.payload.message),
|
|
18979
|
+
route_template: normalizeRoute(event.payload.route ?? null),
|
|
18980
|
+
http_method: null,
|
|
18981
|
+
http_status: null,
|
|
18982
|
+
top_frames: topFrames,
|
|
18983
|
+
browser_event_kind: browserEvent?.kind ?? null,
|
|
18984
|
+
resource_host: resourceIdentity.host,
|
|
18985
|
+
resource_path: resourceIdentity.path,
|
|
18350
18986
|
payload: redactedPayload
|
|
18351
18987
|
};
|
|
18352
18988
|
}
|
|
@@ -18359,6 +18995,9 @@ function normalizeEvent(event) {
|
|
|
18359
18995
|
http_method: null,
|
|
18360
18996
|
http_status: null,
|
|
18361
18997
|
top_frames: [],
|
|
18998
|
+
browser_event_kind: null,
|
|
18999
|
+
resource_host: null,
|
|
19000
|
+
resource_path: null,
|
|
18362
19001
|
payload: redactedPayload
|
|
18363
19002
|
};
|
|
18364
19003
|
}
|
|
@@ -18368,6 +19007,9 @@ function fingerprint(event) {
|
|
|
18368
19007
|
normalized_message: event.normalized_message,
|
|
18369
19008
|
top_frames: event.top_frames,
|
|
18370
19009
|
route_template: event.route_template,
|
|
19010
|
+
browser_event_kind: event.browser_event_kind,
|
|
19011
|
+
resource_host: event.resource_host,
|
|
19012
|
+
resource_path: event.resource_path,
|
|
18371
19013
|
http_method: event.http_method,
|
|
18372
19014
|
http_status: event.http_status,
|
|
18373
19015
|
environment: event.environment
|
|
@@ -18422,18 +19064,18 @@ var ConnectionConfigSchema = external_exports.object({
|
|
|
18422
19064
|
}).strict();
|
|
18423
19065
|
|
|
18424
19066
|
// ../cli/src/doctor-command.ts
|
|
18425
|
-
var ProfileSchema2 = external_exports.object({
|
|
18426
|
-
debugbundle: external_exports.object({
|
|
18427
|
-
last_reviewed_at: external_exports.string(),
|
|
18428
|
-
validation_status: external_exports.enum(["static-analysis-only", "agent-validated"])
|
|
18429
|
-
})
|
|
18430
|
-
});
|
|
18431
19067
|
var HealthResponseSchema = external_exports.object({
|
|
18432
19068
|
status: external_exports.literal("ok")
|
|
18433
19069
|
});
|
|
18434
19070
|
var IncidentsProbeResponseSchema = external_exports.object({
|
|
18435
19071
|
incidents: external_exports.array(external_exports.unknown())
|
|
18436
19072
|
});
|
|
19073
|
+
var DoctorProfileSchema = external_exports.object({
|
|
19074
|
+
debugbundle: external_exports.object({
|
|
19075
|
+
last_reviewed_at: external_exports.string(),
|
|
19076
|
+
validation_status: external_exports.enum(["static-analysis-only", "agent-validated"])
|
|
19077
|
+
})
|
|
19078
|
+
});
|
|
18437
19079
|
var PROFILE_STALENESS_THRESHOLD_DAYS = 30;
|
|
18438
19080
|
var LOCAL_RELAY_SPOOL_DIRECTORY_PATH = ".debugbundle/local/browser-relay-spool";
|
|
18439
19081
|
var RELAY_SPOOL_DELIVERED_MARKER_SUFFIX = ".delivered";
|
|
@@ -18576,6 +19218,12 @@ async function buildFileCheck(rootDirectory, name, filePath, stat) {
|
|
|
18576
19218
|
message: exists ? `Found ${filePath}` : `Missing ${filePath}`
|
|
18577
19219
|
};
|
|
18578
19220
|
}
|
|
19221
|
+
function formatZodErrors2(error) {
|
|
19222
|
+
return error.issues.map((issue) => ({
|
|
19223
|
+
path: issue.path.join("."),
|
|
19224
|
+
message: issue.message
|
|
19225
|
+
}));
|
|
19226
|
+
}
|
|
18579
19227
|
async function loadProfile(rootDirectory, dependencies) {
|
|
18580
19228
|
const profilePath = (0, import_node_path4.join)(rootDirectory, PROFILE_FILE_PATH);
|
|
18581
19229
|
if (!await pathExists3(profilePath, dependencies.stat)) {
|
|
@@ -18585,29 +19233,46 @@ async function loadProfile(rootDirectory, dependencies) {
|
|
|
18585
19233
|
status: "missing",
|
|
18586
19234
|
message: `Missing ${PROFILE_FILE_PATH}`
|
|
18587
19235
|
},
|
|
18588
|
-
profile: null
|
|
19236
|
+
profile: null,
|
|
19237
|
+
validationErrors: []
|
|
18589
19238
|
};
|
|
18590
19239
|
}
|
|
19240
|
+
let parsedJson;
|
|
18591
19241
|
try {
|
|
18592
|
-
|
|
19242
|
+
parsedJson = JSON.parse(await dependencies.readFile(profilePath));
|
|
19243
|
+
} catch {
|
|
18593
19244
|
return {
|
|
18594
19245
|
check: {
|
|
18595
19246
|
name: "profile",
|
|
18596
|
-
status: "
|
|
18597
|
-
message: `
|
|
19247
|
+
status: "error",
|
|
19248
|
+
message: `Invalid ${PROFILE_FILE_PATH}`
|
|
18598
19249
|
},
|
|
18599
|
-
profile:
|
|
19250
|
+
profile: null,
|
|
19251
|
+
validationErrors: []
|
|
18600
19252
|
};
|
|
18601
|
-
}
|
|
19253
|
+
}
|
|
19254
|
+
const parsedDoctorProfile = DoctorProfileSchema.safeParse(parsedJson);
|
|
19255
|
+
if (!parsedDoctorProfile.success) {
|
|
18602
19256
|
return {
|
|
18603
19257
|
check: {
|
|
18604
19258
|
name: "profile",
|
|
18605
19259
|
status: "error",
|
|
18606
19260
|
message: `Invalid ${PROFILE_FILE_PATH}`
|
|
18607
19261
|
},
|
|
18608
|
-
profile: null
|
|
19262
|
+
profile: null,
|
|
19263
|
+
validationErrors: formatZodErrors2(parsedDoctorProfile.error)
|
|
18609
19264
|
};
|
|
18610
19265
|
}
|
|
19266
|
+
const parsedFullProfile = ProfileSchema.safeParse(parsedJson);
|
|
19267
|
+
return {
|
|
19268
|
+
check: {
|
|
19269
|
+
name: "profile",
|
|
19270
|
+
status: "ok",
|
|
19271
|
+
message: `Found ${PROFILE_FILE_PATH}`
|
|
19272
|
+
},
|
|
19273
|
+
profile: parsedDoctorProfile.data,
|
|
19274
|
+
validationErrors: parsedFullProfile.success ? [] : formatZodErrors2(parsedFullProfile.error)
|
|
19275
|
+
};
|
|
18611
19276
|
}
|
|
18612
19277
|
async function loadConnection(rootDirectory, dependencies) {
|
|
18613
19278
|
const connectionPath = (0, import_node_path4.join)(rootDirectory, CONNECTION_FILE_PATH);
|
|
@@ -18659,7 +19324,20 @@ function buildProjectModeCheck(connection) {
|
|
|
18659
19324
|
message: `Project mode is ${connection.mode}.`
|
|
18660
19325
|
};
|
|
18661
19326
|
}
|
|
18662
|
-
function
|
|
19327
|
+
function formatProfileValidationError(errors) {
|
|
19328
|
+
const firstError = errors[0];
|
|
19329
|
+
const path = firstError.path.length === 0 ? PROFILE_FILE_PATH : firstError.path;
|
|
19330
|
+
const totalErrors = errors.length === 1 ? "" : ` (${errors.length} total errors)`;
|
|
19331
|
+
return `Profile schema validation failed at ${path}: ${firstError.message}${totalErrors}.`;
|
|
19332
|
+
}
|
|
19333
|
+
function buildProfileValidationCheck(profile, validationErrors) {
|
|
19334
|
+
if (validationErrors.length > 0) {
|
|
19335
|
+
return {
|
|
19336
|
+
name: "profile-validation",
|
|
19337
|
+
status: "error",
|
|
19338
|
+
message: formatProfileValidationError(validationErrors)
|
|
19339
|
+
};
|
|
19340
|
+
}
|
|
18663
19341
|
if (profile === null) {
|
|
18664
19342
|
return {
|
|
18665
19343
|
name: "profile-validation",
|
|
@@ -18908,7 +19586,7 @@ async function doctorCommand(input, dependencies = {}) {
|
|
|
18908
19586
|
const stat = dependencies.stat ?? import_promises4.stat;
|
|
18909
19587
|
const rootDirectory = cwd();
|
|
18910
19588
|
const currentTime = now();
|
|
18911
|
-
const { check: profileCheck, profile } = await loadProfile(rootDirectory, { readFile, stat });
|
|
19589
|
+
const { check: profileCheck, profile, validationErrors } = await loadProfile(rootDirectory, { readFile, stat });
|
|
18912
19590
|
const { check: connectionCheck, connection } = await loadConnection(rootDirectory, { readFile, stat });
|
|
18913
19591
|
const { check: authCheck, authState } = await buildAuthCheck(input, readAuthStateImpl);
|
|
18914
19592
|
const connectedApiCheck = await buildConnectedApiCheck({
|
|
@@ -18923,7 +19601,7 @@ async function doctorCommand(input, dependencies = {}) {
|
|
|
18923
19601
|
authCheck,
|
|
18924
19602
|
buildProjectModeCheck(connection),
|
|
18925
19603
|
...connectedApiCheck === null ? [] : [connectedApiCheck],
|
|
18926
|
-
buildProfileValidationCheck(profile),
|
|
19604
|
+
buildProfileValidationCheck(profile, validationErrors),
|
|
18927
19605
|
buildProfileFreshnessCheck(profile, currentTime),
|
|
18928
19606
|
...input.checkRelay === true ? [await buildRelaySpoolCheck(rootDirectory, currentTime, { readdir, stat })] : []
|
|
18929
19607
|
];
|
|
@@ -18935,6 +19613,7 @@ async function doctorCommand(input, dependencies = {}) {
|
|
|
18935
19613
|
}
|
|
18936
19614
|
|
|
18937
19615
|
// ../cli/src/verify-command.ts
|
|
19616
|
+
var import_node_crypto6 = require("node:crypto");
|
|
18938
19617
|
var import_promises7 = require("node:fs/promises");
|
|
18939
19618
|
var import_node_path9 = require("node:path");
|
|
18940
19619
|
|
|
@@ -19235,6 +19914,868 @@ var import_ioredis4 = __toESM(require_built3(), 1);
|
|
|
19235
19914
|
|
|
19236
19915
|
// ../../packages/storage/src/schema-migrations.ts
|
|
19237
19916
|
var import_node_crypto3 = require("node:crypto");
|
|
19917
|
+
|
|
19918
|
+
// ../../packages/storage/src/migrations.ts
|
|
19919
|
+
var STORAGE_BOOTSTRAP_STATEMENTS = [
|
|
19920
|
+
`
|
|
19921
|
+
CREATE TABLE users (
|
|
19922
|
+
id uuid PRIMARY KEY,
|
|
19923
|
+
email text NOT NULL UNIQUE,
|
|
19924
|
+
accepted_terms_at timestamptz,
|
|
19925
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
19926
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
19927
|
+
email_verified_at timestamptz,
|
|
19928
|
+
avatar_source text,
|
|
19929
|
+
avatar_object_key text,
|
|
19930
|
+
avatar_content_type text,
|
|
19931
|
+
avatar_updated_at timestamptz
|
|
19932
|
+
)
|
|
19933
|
+
`,
|
|
19934
|
+
`
|
|
19935
|
+
CREATE TABLE organizations (
|
|
19936
|
+
id uuid PRIMARY KEY,
|
|
19937
|
+
name text NOT NULL,
|
|
19938
|
+
slug text NOT NULL UNIQUE,
|
|
19939
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
19940
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
19941
|
+
suspended_at timestamptz,
|
|
19942
|
+
plan text NOT NULL DEFAULT 'free',
|
|
19943
|
+
stripe_customer_id text,
|
|
19944
|
+
additional_capacity_units integer NOT NULL DEFAULT 0,
|
|
19945
|
+
stripe_subscription_id text,
|
|
19946
|
+
billing_state text,
|
|
19947
|
+
billing_period_ends_at timestamptz,
|
|
19948
|
+
last_billing_sync_at timestamptz,
|
|
19949
|
+
last_billing_event_id text,
|
|
19950
|
+
billing_period_starts_at timestamptz
|
|
19951
|
+
)
|
|
19952
|
+
`,
|
|
19953
|
+
`
|
|
19954
|
+
CREATE UNIQUE INDEX organizations_stripe_customer_id_key
|
|
19955
|
+
ON organizations (stripe_customer_id)
|
|
19956
|
+
WHERE stripe_customer_id IS NOT NULL
|
|
19957
|
+
`,
|
|
19958
|
+
`
|
|
19959
|
+
CREATE TABLE projects (
|
|
19960
|
+
id uuid PRIMARY KEY,
|
|
19961
|
+
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
19962
|
+
owner_user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
19963
|
+
name text NOT NULL,
|
|
19964
|
+
slug text NOT NULL,
|
|
19965
|
+
environment_default text NOT NULL DEFAULT 'production',
|
|
19966
|
+
automated_improvement_bundles_enabled boolean NOT NULL DEFAULT true,
|
|
19967
|
+
improvement_bundle_sensitivity text NOT NULL DEFAULT 'high_confidence'
|
|
19968
|
+
CHECK (improvement_bundle_sensitivity IN ('high_confidence', 'balanced', 'verbose')),
|
|
19969
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
19970
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
19971
|
+
plan text NOT NULL DEFAULT 'free'
|
|
19972
|
+
)
|
|
19973
|
+
`,
|
|
19974
|
+
`
|
|
19975
|
+
CREATE UNIQUE INDEX projects_organization_id_slug_key
|
|
19976
|
+
ON projects (organization_id, slug)
|
|
19977
|
+
`,
|
|
19978
|
+
`
|
|
19979
|
+
CREATE TABLE services (
|
|
19980
|
+
id uuid PRIMARY KEY,
|
|
19981
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
19982
|
+
name text NOT NULL,
|
|
19983
|
+
runtime text,
|
|
19984
|
+
framework text,
|
|
19985
|
+
environment text NOT NULL DEFAULT 'production',
|
|
19986
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
19987
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
19988
|
+
UNIQUE (project_id, name, environment)
|
|
19989
|
+
)
|
|
19990
|
+
`,
|
|
19991
|
+
`
|
|
19992
|
+
CREATE TABLE project_tokens (
|
|
19993
|
+
id uuid PRIMARY KEY,
|
|
19994
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
19995
|
+
token_hash text UNIQUE NOT NULL,
|
|
19996
|
+
label text NOT NULL,
|
|
19997
|
+
allowed_origins jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
19998
|
+
last_used_at timestamptz,
|
|
19999
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20000
|
+
revoked_at timestamptz,
|
|
20001
|
+
expires_at timestamptz
|
|
20002
|
+
)
|
|
20003
|
+
`,
|
|
20004
|
+
`
|
|
20005
|
+
CREATE TABLE member_tokens (
|
|
20006
|
+
id uuid PRIMARY KEY,
|
|
20007
|
+
user_id uuid NOT NULL,
|
|
20008
|
+
organization_id uuid NOT NULL,
|
|
20009
|
+
token_hash text UNIQUE NOT NULL,
|
|
20010
|
+
label text NOT NULL,
|
|
20011
|
+
last_used_at timestamptz,
|
|
20012
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20013
|
+
revoked_at timestamptz,
|
|
20014
|
+
expires_at timestamptz
|
|
20015
|
+
)
|
|
20016
|
+
`,
|
|
20017
|
+
`
|
|
20018
|
+
CREATE INDEX member_tokens_org_idx
|
|
20019
|
+
ON member_tokens (organization_id)
|
|
20020
|
+
`,
|
|
20021
|
+
`
|
|
20022
|
+
CREATE TABLE audit_logs (
|
|
20023
|
+
id uuid PRIMARY KEY,
|
|
20024
|
+
organization_id uuid,
|
|
20025
|
+
actor_user_id uuid,
|
|
20026
|
+
actor_type text NOT NULL,
|
|
20027
|
+
action text NOT NULL,
|
|
20028
|
+
target_type text NOT NULL,
|
|
20029
|
+
target_id text,
|
|
20030
|
+
status text NOT NULL,
|
|
20031
|
+
ip_address text,
|
|
20032
|
+
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
20033
|
+
occurred_at timestamptz NOT NULL,
|
|
20034
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
20035
|
+
)
|
|
20036
|
+
`,
|
|
20037
|
+
`
|
|
20038
|
+
CREATE INDEX audit_logs_organization_occurred_at_idx
|
|
20039
|
+
ON audit_logs (organization_id, occurred_at DESC, created_at DESC)
|
|
20040
|
+
`,
|
|
20041
|
+
`
|
|
20042
|
+
CREATE INDEX audit_logs_action_occurred_at_idx
|
|
20043
|
+
ON audit_logs (action, occurred_at DESC, created_at DESC)
|
|
20044
|
+
`,
|
|
20045
|
+
`
|
|
20046
|
+
CREATE TABLE organization_members (
|
|
20047
|
+
id uuid PRIMARY KEY,
|
|
20048
|
+
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
20049
|
+
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
20050
|
+
role text NOT NULL DEFAULT 'member',
|
|
20051
|
+
suspended_at timestamptz,
|
|
20052
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20053
|
+
UNIQUE (organization_id, user_id)
|
|
20054
|
+
)
|
|
20055
|
+
`,
|
|
20056
|
+
`
|
|
20057
|
+
CREATE INDEX organization_members_org_idx
|
|
20058
|
+
ON organization_members (organization_id)
|
|
20059
|
+
`,
|
|
20060
|
+
`
|
|
20061
|
+
CREATE INDEX organization_members_user_idx
|
|
20062
|
+
ON organization_members (user_id)
|
|
20063
|
+
`,
|
|
20064
|
+
`
|
|
20065
|
+
CREATE TABLE sessions (
|
|
20066
|
+
id uuid PRIMARY KEY,
|
|
20067
|
+
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
20068
|
+
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
20069
|
+
session_token_hash text UNIQUE NOT NULL,
|
|
20070
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20071
|
+
expires_at timestamptz NOT NULL,
|
|
20072
|
+
revoked_at timestamptz
|
|
20073
|
+
)
|
|
20074
|
+
`,
|
|
20075
|
+
`
|
|
20076
|
+
CREATE INDEX sessions_token_hash_idx
|
|
20077
|
+
ON sessions (session_token_hash)
|
|
20078
|
+
`,
|
|
20079
|
+
`
|
|
20080
|
+
CREATE INDEX sessions_user_org_idx
|
|
20081
|
+
ON sessions (user_id, organization_id)
|
|
20082
|
+
`,
|
|
20083
|
+
`
|
|
20084
|
+
CREATE TABLE email_auth_challenges (
|
|
20085
|
+
id uuid PRIMARY KEY,
|
|
20086
|
+
email text NOT NULL,
|
|
20087
|
+
code_hash text NOT NULL,
|
|
20088
|
+
accepted_terms_at timestamptz,
|
|
20089
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20090
|
+
expires_at timestamptz NOT NULL,
|
|
20091
|
+
used_at timestamptz
|
|
20092
|
+
)
|
|
20093
|
+
`,
|
|
20094
|
+
`
|
|
20095
|
+
CREATE INDEX email_auth_challenges_email_idx
|
|
20096
|
+
ON email_auth_challenges (lower(email), created_at DESC)
|
|
20097
|
+
`,
|
|
20098
|
+
`
|
|
20099
|
+
CREATE INDEX email_auth_challenges_code_hash_idx
|
|
20100
|
+
ON email_auth_challenges (code_hash)
|
|
20101
|
+
`,
|
|
20102
|
+
`
|
|
20103
|
+
CREATE TABLE github_device_authorizations (
|
|
20104
|
+
id uuid PRIMARY KEY,
|
|
20105
|
+
device_code text NOT NULL UNIQUE,
|
|
20106
|
+
user_code text NOT NULL,
|
|
20107
|
+
verification_uri text NOT NULL,
|
|
20108
|
+
interval_seconds integer NOT NULL,
|
|
20109
|
+
expires_at timestamptz NOT NULL,
|
|
20110
|
+
accepted_terms_at timestamptz,
|
|
20111
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20112
|
+
completed_at timestamptz,
|
|
20113
|
+
claimed_at timestamptz,
|
|
20114
|
+
terminal_error text,
|
|
20115
|
+
user_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
20116
|
+
organization_id uuid REFERENCES organizations(id) ON DELETE SET NULL
|
|
20117
|
+
)
|
|
20118
|
+
`,
|
|
20119
|
+
`
|
|
20120
|
+
CREATE INDEX github_device_authorizations_user_code_idx
|
|
20121
|
+
ON github_device_authorizations (user_code, created_at DESC)
|
|
20122
|
+
`,
|
|
20123
|
+
`
|
|
20124
|
+
CREATE INDEX github_device_authorizations_expires_at_idx
|
|
20125
|
+
ON github_device_authorizations (expires_at)
|
|
20126
|
+
`,
|
|
20127
|
+
`
|
|
20128
|
+
CREATE TABLE project_members (
|
|
20129
|
+
id uuid PRIMARY KEY,
|
|
20130
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20131
|
+
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
20132
|
+
role text NOT NULL,
|
|
20133
|
+
invited_by_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
20134
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20135
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
20136
|
+
UNIQUE (project_id, user_id)
|
|
20137
|
+
)
|
|
20138
|
+
`,
|
|
20139
|
+
`
|
|
20140
|
+
CREATE INDEX project_members_project_id_idx
|
|
20141
|
+
ON project_members (project_id, created_at DESC)
|
|
20142
|
+
`,
|
|
20143
|
+
`
|
|
20144
|
+
CREATE INDEX project_members_user_id_idx
|
|
20145
|
+
ON project_members (user_id, created_at DESC)
|
|
20146
|
+
`,
|
|
20147
|
+
`
|
|
20148
|
+
CREATE TABLE project_invites (
|
|
20149
|
+
id uuid PRIMARY KEY,
|
|
20150
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20151
|
+
email text NOT NULL,
|
|
20152
|
+
role text NOT NULL,
|
|
20153
|
+
invited_by_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
20154
|
+
invite_token_hash text NOT NULL,
|
|
20155
|
+
accepted_at timestamptz,
|
|
20156
|
+
canceled_at timestamptz,
|
|
20157
|
+
expires_at timestamptz NOT NULL,
|
|
20158
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
20159
|
+
)
|
|
20160
|
+
`,
|
|
20161
|
+
`
|
|
20162
|
+
CREATE INDEX project_invites_project_id_idx
|
|
20163
|
+
ON project_invites (project_id, created_at DESC)
|
|
20164
|
+
`,
|
|
20165
|
+
`
|
|
20166
|
+
CREATE UNIQUE INDEX project_invites_pending_project_email_key
|
|
20167
|
+
ON project_invites (project_id, lower(email))
|
|
20168
|
+
WHERE accepted_at IS NULL AND canceled_at IS NULL
|
|
20169
|
+
`,
|
|
20170
|
+
`
|
|
20171
|
+
CREATE UNIQUE INDEX project_invites_invite_token_hash_key
|
|
20172
|
+
ON project_invites (invite_token_hash)
|
|
20173
|
+
`,
|
|
20174
|
+
`
|
|
20175
|
+
CREATE TABLE oauth_identities (
|
|
20176
|
+
id uuid PRIMARY KEY,
|
|
20177
|
+
provider text NOT NULL,
|
|
20178
|
+
provider_user_id text NOT NULL,
|
|
20179
|
+
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
20180
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20181
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
20182
|
+
UNIQUE (provider, provider_user_id)
|
|
20183
|
+
)
|
|
20184
|
+
`,
|
|
20185
|
+
`
|
|
20186
|
+
CREATE INDEX oauth_identities_user_id_idx
|
|
20187
|
+
ON oauth_identities (user_id, provider)
|
|
20188
|
+
`,
|
|
20189
|
+
`
|
|
20190
|
+
CREATE TABLE probe_activations (
|
|
20191
|
+
id uuid PRIMARY KEY,
|
|
20192
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20193
|
+
created_by_member_id uuid NOT NULL,
|
|
20194
|
+
label_pattern text NOT NULL,
|
|
20195
|
+
service text NOT NULL DEFAULT '*',
|
|
20196
|
+
environment text NOT NULL DEFAULT '*',
|
|
20197
|
+
trigger_expires_at timestamptz NOT NULL,
|
|
20198
|
+
expires_at timestamptz NOT NULL,
|
|
20199
|
+
deactivated_at timestamptz,
|
|
20200
|
+
created_at timestamptz NOT NULL DEFAULT now()
|
|
20201
|
+
)
|
|
20202
|
+
`,
|
|
20203
|
+
`
|
|
20204
|
+
CREATE INDEX probe_activations_project_active_idx
|
|
20205
|
+
ON probe_activations (project_id, expires_at DESC)
|
|
20206
|
+
WHERE deactivated_at IS NULL
|
|
20207
|
+
`,
|
|
20208
|
+
`
|
|
20209
|
+
CREATE TABLE capture_policies (
|
|
20210
|
+
project_id uuid PRIMARY KEY REFERENCES projects(id) ON DELETE CASCADE,
|
|
20211
|
+
preset text NOT NULL DEFAULT 'minimal',
|
|
20212
|
+
capture_logs text,
|
|
20213
|
+
capture_request_events text,
|
|
20214
|
+
capture_breadcrumbs text,
|
|
20215
|
+
capture_probe_events text,
|
|
20216
|
+
immediate_client_error_statuses jsonb,
|
|
20217
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
20218
|
+
)
|
|
20219
|
+
`,
|
|
20220
|
+
`
|
|
20221
|
+
CREATE TABLE capture_rules (
|
|
20222
|
+
id uuid PRIMARY KEY,
|
|
20223
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20224
|
+
name text NOT NULL,
|
|
20225
|
+
description text,
|
|
20226
|
+
enabled boolean NOT NULL DEFAULT true,
|
|
20227
|
+
action text NOT NULL,
|
|
20228
|
+
matcher jsonb NOT NULL,
|
|
20229
|
+
sample_rate double precision,
|
|
20230
|
+
sample_event_class text,
|
|
20231
|
+
created_by_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
20232
|
+
created_from_incident_id text,
|
|
20233
|
+
created_from_event_id text,
|
|
20234
|
+
expires_at timestamptz,
|
|
20235
|
+
hit_count bigint NOT NULL DEFAULT 0,
|
|
20236
|
+
last_matched_at timestamptz,
|
|
20237
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20238
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
20239
|
+
)
|
|
20240
|
+
`,
|
|
20241
|
+
`
|
|
20242
|
+
CREATE INDEX capture_rules_project_enabled_idx
|
|
20243
|
+
ON capture_rules (project_id, enabled)
|
|
20244
|
+
`,
|
|
20245
|
+
`
|
|
20246
|
+
CREATE INDEX capture_rules_project_updated_idx
|
|
20247
|
+
ON capture_rules (project_id, updated_at DESC)
|
|
20248
|
+
`,
|
|
20249
|
+
`
|
|
20250
|
+
CREATE TABLE deployments (
|
|
20251
|
+
id uuid PRIMARY KEY,
|
|
20252
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20253
|
+
service_id uuid REFERENCES services(id) ON DELETE SET NULL,
|
|
20254
|
+
environment text NOT NULL,
|
|
20255
|
+
source_event_id uuid UNIQUE NOT NULL,
|
|
20256
|
+
commit_sha text,
|
|
20257
|
+
version text,
|
|
20258
|
+
branch text,
|
|
20259
|
+
deployed_at timestamptz NOT NULL,
|
|
20260
|
+
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
20261
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20262
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
20263
|
+
)
|
|
20264
|
+
`,
|
|
20265
|
+
`
|
|
20266
|
+
CREATE INDEX deployments_project_service_env_deployed_idx
|
|
20267
|
+
ON deployments (project_id, service_id, environment, deployed_at DESC)
|
|
20268
|
+
`,
|
|
20269
|
+
`
|
|
20270
|
+
CREATE TABLE incidents (
|
|
20271
|
+
id uuid PRIMARY KEY,
|
|
20272
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20273
|
+
service_id uuid REFERENCES services(id) ON DELETE SET NULL,
|
|
20274
|
+
environment text NOT NULL DEFAULT 'production',
|
|
20275
|
+
fingerprint text NOT NULL,
|
|
20276
|
+
fingerprint_version text NOT NULL DEFAULT 'v1',
|
|
20277
|
+
title text NOT NULL,
|
|
20278
|
+
severity text NOT NULL,
|
|
20279
|
+
status text NOT NULL DEFAULT 'open',
|
|
20280
|
+
first_seen_at timestamptz NOT NULL,
|
|
20281
|
+
last_seen_at timestamptz NOT NULL,
|
|
20282
|
+
occurrence_count integer NOT NULL DEFAULT 1,
|
|
20283
|
+
matched_fields text[],
|
|
20284
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20285
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
20286
|
+
regressed_at timestamptz,
|
|
20287
|
+
spike_detected_at timestamptz,
|
|
20288
|
+
frequency_occurrences_1m integer,
|
|
20289
|
+
frequency_occurrences_5m integer,
|
|
20290
|
+
frequency_occurrences_1h integer,
|
|
20291
|
+
frequency_occurrences_24h integer,
|
|
20292
|
+
frequency_baseline_1h_per_5m double precision,
|
|
20293
|
+
frequency_spike_ratio_5m_to_1h double precision,
|
|
20294
|
+
frequency_has_sufficient_baseline boolean,
|
|
20295
|
+
frequency_is_spiking boolean,
|
|
20296
|
+
frequency_snapshot_at timestamptz,
|
|
20297
|
+
latest_deployment_id uuid REFERENCES deployments(id) ON DELETE SET NULL,
|
|
20298
|
+
bundle_generation_number integer NOT NULL DEFAULT 0,
|
|
20299
|
+
bundle_created_at timestamptz,
|
|
20300
|
+
bundle_updated_at timestamptz,
|
|
20301
|
+
bundle_source_event_id uuid,
|
|
20302
|
+
bundle_source_occurred_at timestamptz,
|
|
20303
|
+
bundle_trigger text,
|
|
20304
|
+
bundle_failure_reason text,
|
|
20305
|
+
resolved_at timestamptz,
|
|
20306
|
+
resolved_by_member_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
20307
|
+
UNIQUE (project_id, environment, service_id, fingerprint)
|
|
20308
|
+
)
|
|
20309
|
+
`,
|
|
20310
|
+
`
|
|
20311
|
+
CREATE TABLE processed_events (
|
|
20312
|
+
event_id uuid PRIMARY KEY,
|
|
20313
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20314
|
+
event_type text NOT NULL,
|
|
20315
|
+
fingerprint text NOT NULL,
|
|
20316
|
+
normalized_message text NOT NULL,
|
|
20317
|
+
processed_at timestamptz NOT NULL DEFAULT now()
|
|
20318
|
+
)
|
|
20319
|
+
`,
|
|
20320
|
+
`
|
|
20321
|
+
CREATE TABLE improvement_opportunities (
|
|
20322
|
+
id uuid PRIMARY KEY,
|
|
20323
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20324
|
+
service_id uuid REFERENCES services(id) ON DELETE SET NULL,
|
|
20325
|
+
service_name text NOT NULL,
|
|
20326
|
+
environment text NOT NULL DEFAULT 'production',
|
|
20327
|
+
kind text NOT NULL,
|
|
20328
|
+
status text NOT NULL DEFAULT 'open',
|
|
20329
|
+
severity text NOT NULL,
|
|
20330
|
+
confidence numeric NOT NULL,
|
|
20331
|
+
fingerprint text NOT NULL,
|
|
20332
|
+
title text NOT NULL,
|
|
20333
|
+
summary text NOT NULL,
|
|
20334
|
+
occurrence_count integer NOT NULL DEFAULT 1,
|
|
20335
|
+
evidence jsonb NOT NULL,
|
|
20336
|
+
first_detected_at timestamptz NOT NULL,
|
|
20337
|
+
last_detected_at timestamptz NOT NULL,
|
|
20338
|
+
last_source_event_id uuid,
|
|
20339
|
+
related_incident_ids uuid[] NOT NULL DEFAULT '{}',
|
|
20340
|
+
bundle_generation_number integer NOT NULL DEFAULT 0,
|
|
20341
|
+
bundle_created_at timestamptz,
|
|
20342
|
+
bundle_updated_at timestamptz,
|
|
20343
|
+
bundle_source_event_id uuid,
|
|
20344
|
+
bundle_failure_reason text,
|
|
20345
|
+
resolved_at timestamptz,
|
|
20346
|
+
resolved_by_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
20347
|
+
snoozed_until timestamptz,
|
|
20348
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20349
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
20350
|
+
UNIQUE (project_id, fingerprint)
|
|
20351
|
+
)
|
|
20352
|
+
`,
|
|
20353
|
+
`
|
|
20354
|
+
CREATE INDEX improvement_opportunities_project_status_detected_idx
|
|
20355
|
+
ON improvement_opportunities (project_id, status, last_detected_at DESC)
|
|
20356
|
+
`,
|
|
20357
|
+
`
|
|
20358
|
+
CREATE INDEX improvement_opportunities_project_kind_detected_idx
|
|
20359
|
+
ON improvement_opportunities (project_id, kind, last_detected_at DESC)
|
|
20360
|
+
`,
|
|
20361
|
+
`
|
|
20362
|
+
CREATE INDEX improvement_opportunities_project_service_env_idx
|
|
20363
|
+
ON improvement_opportunities (project_id, service_id, environment)
|
|
20364
|
+
`,
|
|
20365
|
+
`
|
|
20366
|
+
CREATE TABLE improvement_opportunity_events (
|
|
20367
|
+
improvement_opportunity_id uuid NOT NULL REFERENCES improvement_opportunities(id) ON DELETE CASCADE,
|
|
20368
|
+
event_id uuid NOT NULL,
|
|
20369
|
+
event_type text NOT NULL,
|
|
20370
|
+
occurred_at timestamptz NOT NULL,
|
|
20371
|
+
PRIMARY KEY (improvement_opportunity_id, event_id)
|
|
20372
|
+
)
|
|
20373
|
+
`,
|
|
20374
|
+
`
|
|
20375
|
+
CREATE INDEX improvement_opportunity_events_detected_idx
|
|
20376
|
+
ON improvement_opportunity_events (improvement_opportunity_id, occurred_at DESC, event_id DESC)
|
|
20377
|
+
`,
|
|
20378
|
+
`
|
|
20379
|
+
CREATE TABLE bundle_generations (
|
|
20380
|
+
id uuid PRIMARY KEY,
|
|
20381
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20382
|
+
incident_id uuid REFERENCES incidents(id) ON DELETE CASCADE,
|
|
20383
|
+
improvement_opportunity_id uuid REFERENCES improvement_opportunities(id) ON DELETE CASCADE,
|
|
20384
|
+
bundle_type text NOT NULL,
|
|
20385
|
+
generation_number integer NOT NULL,
|
|
20386
|
+
source_event_id uuid NOT NULL,
|
|
20387
|
+
source_occurred_at timestamptz NOT NULL,
|
|
20388
|
+
trigger text NOT NULL,
|
|
20389
|
+
created_at timestamptz NOT NULL,
|
|
20390
|
+
updated_at timestamptz NOT NULL,
|
|
20391
|
+
CHECK (
|
|
20392
|
+
(incident_id IS NOT NULL AND improvement_opportunity_id IS NULL AND bundle_type = 'failure')
|
|
20393
|
+
OR (incident_id IS NULL AND improvement_opportunity_id IS NOT NULL AND bundle_type = 'improvement')
|
|
20394
|
+
)
|
|
20395
|
+
)
|
|
20396
|
+
`,
|
|
20397
|
+
`
|
|
20398
|
+
CREATE UNIQUE INDEX bundle_generations_incident_source_idx
|
|
20399
|
+
ON bundle_generations (incident_id, source_event_id)
|
|
20400
|
+
WHERE incident_id IS NOT NULL
|
|
20401
|
+
`,
|
|
20402
|
+
`
|
|
20403
|
+
CREATE UNIQUE INDEX bundle_generations_improvement_source_idx
|
|
20404
|
+
ON bundle_generations (improvement_opportunity_id, source_event_id)
|
|
20405
|
+
WHERE improvement_opportunity_id IS NOT NULL
|
|
20406
|
+
`,
|
|
20407
|
+
`
|
|
20408
|
+
CREATE INDEX bundle_generations_project_created_idx
|
|
20409
|
+
ON bundle_generations (project_id, created_at DESC, bundle_type)
|
|
20410
|
+
`,
|
|
20411
|
+
`
|
|
20412
|
+
CREATE INDEX bundle_generations_incident_generation_idx
|
|
20413
|
+
ON bundle_generations (incident_id, generation_number DESC)
|
|
20414
|
+
`,
|
|
20415
|
+
`
|
|
20416
|
+
CREATE INDEX bundle_generations_improvement_generation_idx
|
|
20417
|
+
ON bundle_generations (improvement_opportunity_id, generation_number DESC)
|
|
20418
|
+
WHERE improvement_opportunity_id IS NOT NULL
|
|
20419
|
+
`,
|
|
20420
|
+
`
|
|
20421
|
+
CREATE TABLE incident_events (
|
|
20422
|
+
incident_id uuid NOT NULL REFERENCES incidents(id) ON DELETE CASCADE,
|
|
20423
|
+
event_id uuid NOT NULL,
|
|
20424
|
+
event_type text NOT NULL,
|
|
20425
|
+
event_class text NOT NULL DEFAULT 'context_signal',
|
|
20426
|
+
occurred_at timestamptz NOT NULL,
|
|
20427
|
+
is_sampled boolean NOT NULL DEFAULT false,
|
|
20428
|
+
level text,
|
|
20429
|
+
retain_first boolean NOT NULL DEFAULT false,
|
|
20430
|
+
retain_latest boolean NOT NULL DEFAULT false,
|
|
20431
|
+
retain_after_deploy boolean NOT NULL DEFAULT false,
|
|
20432
|
+
retain_highest_severity boolean NOT NULL DEFAULT false,
|
|
20433
|
+
retain_deploy_metadata boolean NOT NULL DEFAULT false,
|
|
20434
|
+
severity_rank integer NOT NULL DEFAULT 0,
|
|
20435
|
+
PRIMARY KEY (incident_id, event_id)
|
|
20436
|
+
)
|
|
20437
|
+
`,
|
|
20438
|
+
`
|
|
20439
|
+
CREATE INDEX incident_events_incident_occurred_event_idx
|
|
20440
|
+
ON incident_events (incident_id, occurred_at DESC, event_id DESC)
|
|
20441
|
+
`,
|
|
20442
|
+
`
|
|
20443
|
+
CREATE INDEX incident_events_incident_level_occurred_event_idx
|
|
20444
|
+
ON incident_events (incident_id, level, occurred_at DESC, event_id DESC)
|
|
20445
|
+
`,
|
|
20446
|
+
`
|
|
20447
|
+
CREATE INDEX incident_events_incident_sampled_idx
|
|
20448
|
+
ON incident_events (incident_id, is_sampled, occurred_at ASC, event_id ASC)
|
|
20449
|
+
`,
|
|
20450
|
+
`
|
|
20451
|
+
CREATE TABLE weekly_report_channels (
|
|
20452
|
+
id uuid PRIMARY KEY,
|
|
20453
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20454
|
+
channel text NOT NULL,
|
|
20455
|
+
config jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
20456
|
+
schedule_day_of_week text NOT NULL,
|
|
20457
|
+
schedule_hour_of_day integer NOT NULL,
|
|
20458
|
+
schedule_timezone text NOT NULL,
|
|
20459
|
+
is_enabled boolean NOT NULL DEFAULT true,
|
|
20460
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20461
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
20462
|
+
)
|
|
20463
|
+
`,
|
|
20464
|
+
`
|
|
20465
|
+
CREATE INDEX weekly_report_channels_project_created_idx
|
|
20466
|
+
ON weekly_report_channels (project_id, created_at ASC)
|
|
20467
|
+
`,
|
|
20468
|
+
`
|
|
20469
|
+
CREATE UNIQUE INDEX weekly_report_channels_project_email_unique_idx
|
|
20470
|
+
ON weekly_report_channels (project_id)
|
|
20471
|
+
WHERE channel = 'email'
|
|
20472
|
+
`,
|
|
20473
|
+
`
|
|
20474
|
+
CREATE TABLE weekly_report_deliveries (
|
|
20475
|
+
id uuid PRIMARY KEY,
|
|
20476
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20477
|
+
weekly_report_channel_id uuid REFERENCES weekly_report_channels(id) ON DELETE CASCADE,
|
|
20478
|
+
window_start timestamptz NOT NULL,
|
|
20479
|
+
window_end timestamptz NOT NULL,
|
|
20480
|
+
channel text NOT NULL,
|
|
20481
|
+
status text NOT NULL,
|
|
20482
|
+
last_error text,
|
|
20483
|
+
delivered_at timestamptz,
|
|
20484
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20485
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
20486
|
+
)
|
|
20487
|
+
`,
|
|
20488
|
+
`
|
|
20489
|
+
CREATE INDEX weekly_report_deliveries_project_window_idx
|
|
20490
|
+
ON weekly_report_deliveries (project_id, window_end DESC, channel)
|
|
20491
|
+
`,
|
|
20492
|
+
`
|
|
20493
|
+
CREATE UNIQUE INDEX weekly_report_deliveries_channel_window_idx
|
|
20494
|
+
ON weekly_report_deliveries (weekly_report_channel_id, window_start, window_end)
|
|
20495
|
+
WHERE weekly_report_channel_id IS NOT NULL
|
|
20496
|
+
`,
|
|
20497
|
+
`
|
|
20498
|
+
CREATE INDEX weekly_report_deliveries_channel_idx
|
|
20499
|
+
ON weekly_report_deliveries (weekly_report_channel_id, window_end DESC)
|
|
20500
|
+
`,
|
|
20501
|
+
`
|
|
20502
|
+
CREATE TABLE alert_rules (
|
|
20503
|
+
id uuid PRIMARY KEY,
|
|
20504
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20505
|
+
created_by_user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
20506
|
+
service_id uuid REFERENCES services(id) ON DELETE CASCADE,
|
|
20507
|
+
channel text NOT NULL,
|
|
20508
|
+
condition_type text NOT NULL,
|
|
20509
|
+
severity_min text,
|
|
20510
|
+
config jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
20511
|
+
is_enabled boolean NOT NULL DEFAULT true,
|
|
20512
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20513
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
20514
|
+
)
|
|
20515
|
+
`,
|
|
20516
|
+
`
|
|
20517
|
+
CREATE INDEX alert_rules_project_enabled_idx
|
|
20518
|
+
ON alert_rules (project_id, is_enabled)
|
|
20519
|
+
`,
|
|
20520
|
+
`
|
|
20521
|
+
CREATE TABLE slack_destinations (
|
|
20522
|
+
id uuid PRIMARY KEY,
|
|
20523
|
+
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
20524
|
+
slack_team_id text NOT NULL,
|
|
20525
|
+
slack_team_name text,
|
|
20526
|
+
slack_channel_id text NOT NULL,
|
|
20527
|
+
slack_channel_name text,
|
|
20528
|
+
webhook_url_ciphertext text NOT NULL,
|
|
20529
|
+
installed_by_member_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
20530
|
+
is_active boolean NOT NULL DEFAULT true,
|
|
20531
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20532
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
20533
|
+
UNIQUE (organization_id, slack_team_id, slack_channel_id)
|
|
20534
|
+
)
|
|
20535
|
+
`,
|
|
20536
|
+
`
|
|
20537
|
+
CREATE INDEX slack_destinations_org_active_idx
|
|
20538
|
+
ON slack_destinations (organization_id, is_active, created_at)
|
|
20539
|
+
`,
|
|
20540
|
+
`
|
|
20541
|
+
CREATE TABLE alert_deliveries (
|
|
20542
|
+
id uuid PRIMARY KEY,
|
|
20543
|
+
alert_id uuid NOT NULL REFERENCES alert_rules(id) ON DELETE CASCADE,
|
|
20544
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20545
|
+
incident_id uuid NOT NULL REFERENCES incidents(id) ON DELETE CASCADE,
|
|
20546
|
+
condition_type text NOT NULL,
|
|
20547
|
+
dedupe_key text NOT NULL,
|
|
20548
|
+
channel text NOT NULL,
|
|
20549
|
+
status text NOT NULL,
|
|
20550
|
+
payload jsonb NOT NULL,
|
|
20551
|
+
last_error text,
|
|
20552
|
+
delivered_at timestamptz,
|
|
20553
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20554
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
20555
|
+
UNIQUE (alert_id, incident_id, dedupe_key)
|
|
20556
|
+
)
|
|
20557
|
+
`,
|
|
20558
|
+
`
|
|
20559
|
+
CREATE INDEX alert_deliveries_project_status_idx
|
|
20560
|
+
ON alert_deliveries (project_id, status, created_at DESC)
|
|
20561
|
+
`,
|
|
20562
|
+
`
|
|
20563
|
+
CREATE TABLE alert_email_digests (
|
|
20564
|
+
id uuid PRIMARY KEY,
|
|
20565
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20566
|
+
recipient text NOT NULL,
|
|
20567
|
+
status text NOT NULL,
|
|
20568
|
+
next_attempt_at timestamptz,
|
|
20569
|
+
claimed_at timestamptz,
|
|
20570
|
+
last_error text,
|
|
20571
|
+
delivered_at timestamptz,
|
|
20572
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20573
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
20574
|
+
)
|
|
20575
|
+
`,
|
|
20576
|
+
`
|
|
20577
|
+
CREATE UNIQUE INDEX alert_email_digests_project_recipient_pending_idx
|
|
20578
|
+
ON alert_email_digests (project_id, recipient)
|
|
20579
|
+
WHERE status = 'pending' AND claimed_at IS NULL
|
|
20580
|
+
`,
|
|
20581
|
+
`
|
|
20582
|
+
CREATE INDEX alert_email_digests_status_next_attempt_idx
|
|
20583
|
+
ON alert_email_digests (status, next_attempt_at)
|
|
20584
|
+
`,
|
|
20585
|
+
`
|
|
20586
|
+
CREATE TABLE alert_email_digest_items (
|
|
20587
|
+
id uuid PRIMARY KEY,
|
|
20588
|
+
digest_id uuid NOT NULL REFERENCES alert_email_digests(id) ON DELETE CASCADE,
|
|
20589
|
+
alert_id uuid NOT NULL REFERENCES alert_rules(id) ON DELETE CASCADE,
|
|
20590
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20591
|
+
incident_id uuid NOT NULL REFERENCES incidents(id) ON DELETE CASCADE,
|
|
20592
|
+
condition_type text NOT NULL,
|
|
20593
|
+
dedupe_key text NOT NULL,
|
|
20594
|
+
payload jsonb NOT NULL,
|
|
20595
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20596
|
+
UNIQUE (alert_id, incident_id, dedupe_key)
|
|
20597
|
+
)
|
|
20598
|
+
`,
|
|
20599
|
+
`
|
|
20600
|
+
CREATE INDEX alert_email_digest_items_digest_created_idx
|
|
20601
|
+
ON alert_email_digest_items (digest_id, created_at ASC)
|
|
20602
|
+
`,
|
|
20603
|
+
`
|
|
20604
|
+
CREATE TABLE agent_webhooks (
|
|
20605
|
+
id uuid PRIMARY KEY,
|
|
20606
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20607
|
+
created_by_user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
20608
|
+
url text NOT NULL,
|
|
20609
|
+
secret_hash text NOT NULL,
|
|
20610
|
+
events text[] NOT NULL,
|
|
20611
|
+
filters jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
20612
|
+
is_enabled boolean NOT NULL DEFAULT true,
|
|
20613
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20614
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
20615
|
+
)
|
|
20616
|
+
`,
|
|
20617
|
+
`
|
|
20618
|
+
CREATE INDEX agent_webhooks_project_enabled_idx
|
|
20619
|
+
ON agent_webhooks (project_id, is_enabled)
|
|
20620
|
+
`,
|
|
20621
|
+
`
|
|
20622
|
+
CREATE TABLE webhook_deliveries (
|
|
20623
|
+
id uuid PRIMARY KEY,
|
|
20624
|
+
webhook_id uuid REFERENCES agent_webhooks(id) ON DELETE CASCADE,
|
|
20625
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20626
|
+
incident_id uuid REFERENCES incidents(id) ON DELETE CASCADE,
|
|
20627
|
+
event_type text NOT NULL,
|
|
20628
|
+
target_url text NOT NULL,
|
|
20629
|
+
signing_secret text NOT NULL,
|
|
20630
|
+
status text NOT NULL DEFAULT 'pending',
|
|
20631
|
+
attempt_count integer NOT NULL DEFAULT 0,
|
|
20632
|
+
occurred_at timestamptz NOT NULL,
|
|
20633
|
+
next_attempt_at timestamptz,
|
|
20634
|
+
last_response_code integer,
|
|
20635
|
+
last_attempted_at timestamptz,
|
|
20636
|
+
last_error text,
|
|
20637
|
+
payload jsonb NOT NULL,
|
|
20638
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20639
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
20640
|
+
)
|
|
20641
|
+
`,
|
|
20642
|
+
`
|
|
20643
|
+
CREATE INDEX webhook_deliveries_status_next_attempt_idx
|
|
20644
|
+
ON webhook_deliveries (status, next_attempt_at)
|
|
20645
|
+
`,
|
|
20646
|
+
`
|
|
20647
|
+
CREATE TABLE processed_billing_events (
|
|
20648
|
+
event_id text PRIMARY KEY,
|
|
20649
|
+
event_type text NOT NULL,
|
|
20650
|
+
organization_id uuid,
|
|
20651
|
+
processed_at timestamptz NOT NULL DEFAULT now()
|
|
20652
|
+
)
|
|
20653
|
+
`,
|
|
20654
|
+
`
|
|
20655
|
+
CREATE TABLE github_installations (
|
|
20656
|
+
id uuid PRIMARY KEY,
|
|
20657
|
+
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
20658
|
+
installation_id bigint NOT NULL UNIQUE,
|
|
20659
|
+
account_login text NOT NULL,
|
|
20660
|
+
account_type text NOT NULL CHECK (account_type IN ('Organization', 'User')),
|
|
20661
|
+
status text NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'suspended', 'removed')),
|
|
20662
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20663
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
20664
|
+
UNIQUE (organization_id)
|
|
20665
|
+
)
|
|
20666
|
+
`,
|
|
20667
|
+
`
|
|
20668
|
+
CREATE INDEX github_installations_status_idx
|
|
20669
|
+
ON github_installations (status)
|
|
20670
|
+
`,
|
|
20671
|
+
`
|
|
20672
|
+
CREATE TABLE project_github_repos (
|
|
20673
|
+
id uuid PRIMARY KEY,
|
|
20674
|
+
project_id uuid NOT NULL UNIQUE REFERENCES projects(id) ON DELETE CASCADE,
|
|
20675
|
+
installation_id uuid NOT NULL REFERENCES github_installations(id) ON DELETE CASCADE,
|
|
20676
|
+
repo_owner text NOT NULL,
|
|
20677
|
+
repo_name text NOT NULL,
|
|
20678
|
+
default_branch text NOT NULL DEFAULT 'main',
|
|
20679
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20680
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
20681
|
+
)
|
|
20682
|
+
`,
|
|
20683
|
+
`
|
|
20684
|
+
CREATE TABLE github_dispatch_rules (
|
|
20685
|
+
id uuid PRIMARY KEY,
|
|
20686
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20687
|
+
created_by_user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
20688
|
+
name text NOT NULL,
|
|
20689
|
+
enabled boolean NOT NULL DEFAULT true,
|
|
20690
|
+
event_types text[] NOT NULL,
|
|
20691
|
+
environments text[],
|
|
20692
|
+
services text[],
|
|
20693
|
+
severity_min text CHECK (severity_min IN ('low', 'medium', 'high', 'critical')),
|
|
20694
|
+
bundle_type text CHECK (bundle_type IN ('failure', 'improvement')),
|
|
20695
|
+
incident_status text NOT NULL DEFAULT 'new_or_reopened'
|
|
20696
|
+
CHECK (incident_status IN ('new_only', 'reopened_only', 'new_or_reopened')),
|
|
20697
|
+
cooldown_seconds integer NOT NULL DEFAULT 300,
|
|
20698
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20699
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
20700
|
+
)
|
|
20701
|
+
`,
|
|
20702
|
+
`
|
|
20703
|
+
CREATE INDEX github_dispatch_rules_project_enabled_idx
|
|
20704
|
+
ON github_dispatch_rules (project_id, enabled)
|
|
20705
|
+
`,
|
|
20706
|
+
`
|
|
20707
|
+
CREATE TABLE github_dispatch_deliveries (
|
|
20708
|
+
id uuid PRIMARY KEY,
|
|
20709
|
+
rule_id uuid NOT NULL REFERENCES github_dispatch_rules(id) ON DELETE CASCADE,
|
|
20710
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20711
|
+
incident_id uuid REFERENCES incidents(id) ON DELETE CASCADE,
|
|
20712
|
+
improvement_opportunity_id uuid REFERENCES improvement_opportunities(id) ON DELETE CASCADE,
|
|
20713
|
+
target_fingerprint text NOT NULL,
|
|
20714
|
+
installation_id bigint NOT NULL,
|
|
20715
|
+
repo_owner text NOT NULL,
|
|
20716
|
+
repo_name text NOT NULL,
|
|
20717
|
+
status text NOT NULL DEFAULT 'pending'
|
|
20718
|
+
CHECK (status IN ('pending', 'retrying', 'delivered', 'failed', 'skipped')),
|
|
20719
|
+
attempt_count integer NOT NULL DEFAULT 0,
|
|
20720
|
+
next_attempt_at timestamptz,
|
|
20721
|
+
last_attempt_at timestamptz,
|
|
20722
|
+
last_error text,
|
|
20723
|
+
github_status_code integer,
|
|
20724
|
+
dispatch_payload jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
20725
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20726
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
20727
|
+
dedupe_key text NOT NULL,
|
|
20728
|
+
CHECK (
|
|
20729
|
+
(incident_id IS NOT NULL AND improvement_opportunity_id IS NULL)
|
|
20730
|
+
OR (incident_id IS NULL AND improvement_opportunity_id IS NOT NULL)
|
|
20731
|
+
)
|
|
20732
|
+
)
|
|
20733
|
+
`,
|
|
20734
|
+
`
|
|
20735
|
+
CREATE INDEX github_dispatch_deliveries_status_next_attempt_idx
|
|
20736
|
+
ON github_dispatch_deliveries (status, next_attempt_at)
|
|
20737
|
+
`,
|
|
20738
|
+
`
|
|
20739
|
+
CREATE UNIQUE INDEX github_dispatch_deliveries_rule_dedupe_key_idx
|
|
20740
|
+
ON github_dispatch_deliveries (rule_id, target_fingerprint, dedupe_key)
|
|
20741
|
+
`,
|
|
20742
|
+
`
|
|
20743
|
+
CREATE TABLE org_usage_counters (
|
|
20744
|
+
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
20745
|
+
period_starts_at timestamptz NOT NULL,
|
|
20746
|
+
raw_ingested_events integer NOT NULL DEFAULT 0,
|
|
20747
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
20748
|
+
PRIMARY KEY (organization_id, period_starts_at)
|
|
20749
|
+
)
|
|
20750
|
+
`,
|
|
20751
|
+
`
|
|
20752
|
+
CREATE TABLE operational_email_deliveries (
|
|
20753
|
+
id uuid PRIMARY KEY,
|
|
20754
|
+
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
20755
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
20756
|
+
kind text NOT NULL
|
|
20757
|
+
CHECK (kind IN ('webhook_auto_disabled', 'allowance_warning_80', 'allowance_limit_reached', 'retention_rotation_notice')),
|
|
20758
|
+
dedupe_key text NOT NULL,
|
|
20759
|
+
payload jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
20760
|
+
status text NOT NULL DEFAULT 'pending'
|
|
20761
|
+
CHECK (status IN ('pending', 'retrying', 'delivered', 'failed')),
|
|
20762
|
+
attempt_count integer NOT NULL DEFAULT 0,
|
|
20763
|
+
next_attempt_at timestamptz,
|
|
20764
|
+
last_error text,
|
|
20765
|
+
delivered_at timestamptz,
|
|
20766
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
20767
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
20768
|
+
UNIQUE (organization_id, kind, dedupe_key)
|
|
20769
|
+
)
|
|
20770
|
+
`,
|
|
20771
|
+
`
|
|
20772
|
+
CREATE INDEX operational_email_deliveries_status_next_attempt_idx
|
|
20773
|
+
ON operational_email_deliveries (status, next_attempt_at, created_at)
|
|
20774
|
+
`
|
|
20775
|
+
];
|
|
20776
|
+
var STORAGE_BOOTSTRAP_SQL = STORAGE_BOOTSTRAP_STATEMENTS.join(";\n\n");
|
|
20777
|
+
|
|
20778
|
+
// ../../packages/storage/src/schema-migrations.ts
|
|
19238
20779
|
function computeMigrationChecksum(input) {
|
|
19239
20780
|
return (0, import_node_crypto3.createHash)("sha256").update(JSON.stringify(input)).digest("hex");
|
|
19240
20781
|
}
|
|
@@ -19656,6 +21197,76 @@ var STORAGE_SCHEMA_MIGRATIONS = [
|
|
|
19656
21197
|
statements: [
|
|
19657
21198
|
"ALTER TABLE project_tokens ADD COLUMN IF NOT EXISTS allowed_origins jsonb NOT NULL DEFAULT '[]'::jsonb"
|
|
19658
21199
|
]
|
|
21200
|
+
}),
|
|
21201
|
+
defineStorageSchemaMigration({
|
|
21202
|
+
id: "202605260001_fix_weekly_report_delivery_conflict_index",
|
|
21203
|
+
description: "Ensure weekly report delivery dedupe rows and partial unique index exist for conflict claims.",
|
|
21204
|
+
statements: [
|
|
21205
|
+
`
|
|
21206
|
+
DELETE FROM weekly_report_deliveries
|
|
21207
|
+
WHERE id IN (
|
|
21208
|
+
SELECT id
|
|
21209
|
+
FROM (
|
|
21210
|
+
SELECT
|
|
21211
|
+
id,
|
|
21212
|
+
row_number() OVER (
|
|
21213
|
+
PARTITION BY weekly_report_channel_id, window_start, window_end
|
|
21214
|
+
ORDER BY created_at ASC, id ASC
|
|
21215
|
+
) AS row_number
|
|
21216
|
+
FROM weekly_report_deliveries
|
|
21217
|
+
WHERE weekly_report_channel_id IS NOT NULL
|
|
21218
|
+
) ranked
|
|
21219
|
+
WHERE ranked.row_number > 1
|
|
21220
|
+
)
|
|
21221
|
+
`,
|
|
21222
|
+
`
|
|
21223
|
+
CREATE UNIQUE INDEX IF NOT EXISTS weekly_report_deliveries_channel_window_idx
|
|
21224
|
+
ON weekly_report_deliveries (weekly_report_channel_id, window_start, window_end)
|
|
21225
|
+
WHERE weekly_report_channel_id IS NOT NULL
|
|
21226
|
+
`
|
|
21227
|
+
]
|
|
21228
|
+
}),
|
|
21229
|
+
defineStorageSchemaMigration({
|
|
21230
|
+
id: "202605260001_set_high_confidence_as_project_improvement_default",
|
|
21231
|
+
description: "Make high-confidence the default hosted improvement sensitivity for new projects.",
|
|
21232
|
+
statements: [
|
|
21233
|
+
"ALTER TABLE projects ALTER COLUMN improvement_bundle_sensitivity SET DEFAULT 'high_confidence'"
|
|
21234
|
+
]
|
|
21235
|
+
}),
|
|
21236
|
+
defineStorageSchemaMigration({
|
|
21237
|
+
id: "202605260002_add_capture_rules",
|
|
21238
|
+
description: "Add persisted project capture rules for dynamic demote/sample/drop handling.",
|
|
21239
|
+
statements: [
|
|
21240
|
+
`
|
|
21241
|
+
CREATE TABLE IF NOT EXISTS capture_rules (
|
|
21242
|
+
id uuid PRIMARY KEY,
|
|
21243
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
21244
|
+
name text NOT NULL,
|
|
21245
|
+
description text,
|
|
21246
|
+
enabled boolean NOT NULL DEFAULT true,
|
|
21247
|
+
action text NOT NULL,
|
|
21248
|
+
matcher jsonb NOT NULL,
|
|
21249
|
+
sample_rate double precision,
|
|
21250
|
+
sample_event_class text,
|
|
21251
|
+
created_by_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
|
|
21252
|
+
created_from_incident_id text,
|
|
21253
|
+
created_from_event_id text,
|
|
21254
|
+
expires_at timestamptz,
|
|
21255
|
+
hit_count bigint NOT NULL DEFAULT 0,
|
|
21256
|
+
last_matched_at timestamptz,
|
|
21257
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
21258
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
21259
|
+
)
|
|
21260
|
+
`,
|
|
21261
|
+
`
|
|
21262
|
+
CREATE INDEX IF NOT EXISTS capture_rules_project_enabled_idx
|
|
21263
|
+
ON capture_rules (project_id, enabled)
|
|
21264
|
+
`,
|
|
21265
|
+
`
|
|
21266
|
+
CREATE INDEX IF NOT EXISTS capture_rules_project_updated_idx
|
|
21267
|
+
ON capture_rules (project_id, updated_at DESC)
|
|
21268
|
+
`
|
|
21269
|
+
]
|
|
19659
21270
|
})
|
|
19660
21271
|
];
|
|
19661
21272
|
|
|
@@ -19778,11 +21389,17 @@ function normalizeRouteTemplate(path) {
|
|
|
19778
21389
|
const normalizedSegments = pathWithoutQueryOrFragment.split("/").filter((segment) => segment.length > 0).map((segment) => isDynamicRouteSegment2(segment) ? "{param}" : segment);
|
|
19779
21390
|
return normalizedSegments.length === 0 ? "/" : `/${normalizedSegments.join("/")}`;
|
|
19780
21391
|
}
|
|
21392
|
+
function isBrowserSdkFallbackFrame(frame) {
|
|
21393
|
+
return frame.includes("debugbundle-browser-sdk") && frame.includes("onError");
|
|
21394
|
+
}
|
|
19781
21395
|
function deriveFirstApplicationFrame(errorContext) {
|
|
19782
21396
|
const firstFrame = errorContext?.top_frames[0];
|
|
19783
21397
|
if (firstFrame === void 0) {
|
|
19784
21398
|
return null;
|
|
19785
21399
|
}
|
|
21400
|
+
if (isBrowserSdkFallbackFrame(firstFrame)) {
|
|
21401
|
+
return null;
|
|
21402
|
+
}
|
|
19786
21403
|
const match = /at\s+(.*?)\s+\((.*?):(\d+):(\d+)\)$/.exec(firstFrame) ?? /at\s+(.*?):(\d+):(\d+)$/.exec(firstFrame);
|
|
19787
21404
|
if (match === null) {
|
|
19788
21405
|
return {
|
|
@@ -19804,6 +21421,20 @@ function deriveFirstApplicationFrame(errorContext) {
|
|
|
19804
21421
|
line: Number(match[2])
|
|
19805
21422
|
};
|
|
19806
21423
|
}
|
|
21424
|
+
function getPrimaryBrowserExceptionEvent(envelopes, primarySignalEnvelope) {
|
|
21425
|
+
if (primarySignalEnvelope !== null && isFrontendExceptionEnvelope(primarySignalEnvelope)) {
|
|
21426
|
+
return primarySignalEnvelope.payload.browser_event ?? null;
|
|
21427
|
+
}
|
|
21428
|
+
const envelope = selectLatestEnvelopeByType(envelopes, isFrontendExceptionEnvelope);
|
|
21429
|
+
return envelope?.payload.browser_event ?? null;
|
|
21430
|
+
}
|
|
21431
|
+
function isOpaqueBrowserError(errorContext, browserEvent) {
|
|
21432
|
+
if (browserEvent?.opaque === true) {
|
|
21433
|
+
return true;
|
|
21434
|
+
}
|
|
21435
|
+
const firstFrame = errorContext?.top_frames[0];
|
|
21436
|
+
return errorContext?.message === "Window error" && firstFrame !== void 0 && isBrowserSdkFallbackFrame(firstFrame);
|
|
21437
|
+
}
|
|
19807
21438
|
function buildErrorContext(envelopes, incident, primarySignalEnvelope) {
|
|
19808
21439
|
if (primarySignalEnvelope !== null && isBackendExceptionEnvelope(primarySignalEnvelope)) {
|
|
19809
21440
|
return {
|
|
@@ -19926,6 +21557,20 @@ function buildSummaryGuidance(input) {
|
|
|
19926
21557
|
recommended_action: null
|
|
19927
21558
|
};
|
|
19928
21559
|
}
|
|
21560
|
+
if (input.opaqueBrowserError) {
|
|
21561
|
+
if (input.browserEvent?.kind === "resource_error") {
|
|
21562
|
+
return {
|
|
21563
|
+
likely_cause: "The browser reported a resource load error without a usable application stack.",
|
|
21564
|
+
confidence: 0.35,
|
|
21565
|
+
recommended_action: "Inspect the captured resource target, browser network failures, CSP rules, and cross-origin asset configuration."
|
|
21566
|
+
};
|
|
21567
|
+
}
|
|
21568
|
+
return {
|
|
21569
|
+
likely_cause: "The browser reported an opaque window error without a usable application stack.",
|
|
21570
|
+
confidence: 0.35,
|
|
21571
|
+
recommended_action: "Inspect browser console output, resource loading, cross-origin script settings, and framework-level error boundaries for the affected route."
|
|
21572
|
+
};
|
|
21573
|
+
}
|
|
19929
21574
|
const route = input.requestContext?.route_template ?? input.requestContext?.path ?? null;
|
|
19930
21575
|
const requestDescription = input.requestContext !== null ? `${input.requestContext.method} ${route ?? input.requestContext.path}` : null;
|
|
19931
21576
|
const firstDependency = input.dependenciesContext?.items[0] ?? null;
|
|
@@ -20112,7 +21757,8 @@ function buildFrontendContext(envelopes) {
|
|
|
20112
21757
|
message: envelope.payload.message,
|
|
20113
21758
|
route: envelope.payload.route ?? null,
|
|
20114
21759
|
browser: envelope.payload.browser,
|
|
20115
|
-
ts: toIsoTimestamp(envelope.occurred_at)
|
|
21760
|
+
ts: toIsoTimestamp(envelope.occurred_at),
|
|
21761
|
+
...envelope.payload.browser_event !== void 0 ? { browser_event: envelope.payload.browser_event } : {}
|
|
20116
21762
|
});
|
|
20117
21763
|
}
|
|
20118
21764
|
}
|
|
@@ -20255,6 +21901,8 @@ function buildBundle(input) {
|
|
|
20255
21901
|
const gitContext = buildGitContext(sourceEnvelopes, input.configuredDeploy);
|
|
20256
21902
|
const deviceContext = buildDeviceContext(sourceEnvelopes);
|
|
20257
21903
|
const dependenciesContext = buildDependenciesContext(input.incident, errorContext, requestContext);
|
|
21904
|
+
const browserEvent = getPrimaryBrowserExceptionEvent(sourceEnvelopes, primarySignalEnvelope);
|
|
21905
|
+
const opaqueBrowserError = isOpaqueBrowserError(errorContext, browserEvent);
|
|
20258
21906
|
const primarySignalType = primarySignalEnvelope !== null ? mapSignalType(primarySignalEnvelope.event_type) : inferSignalTypeFromSourceEventTypes(sourceEventTypes);
|
|
20259
21907
|
const primarySourceEvent = errorContext?.name ?? sourceEventTypes[0] ?? "backend_exception";
|
|
20260
21908
|
const firstSeenAt = new Date(input.incident.first_seen_at).toISOString();
|
|
@@ -20269,7 +21917,9 @@ function buildBundle(input) {
|
|
|
20269
21917
|
requestContext,
|
|
20270
21918
|
responseContext,
|
|
20271
21919
|
dependenciesContext,
|
|
20272
|
-
firstApplicationFrame
|
|
21920
|
+
firstApplicationFrame,
|
|
21921
|
+
browserEvent,
|
|
21922
|
+
opaqueBrowserError
|
|
20273
21923
|
});
|
|
20274
21924
|
const candidate = {
|
|
20275
21925
|
bundle_version: 1,
|
|
@@ -21407,7 +23057,7 @@ async function processCommand(input, dependencies = {}) {
|
|
|
21407
23057
|
|
|
21408
23058
|
// ../cli/src/ingest-command.ts
|
|
21409
23059
|
var LOCAL_EVENTS_DIRECTORY_PATH2 = ".debugbundle/local/events";
|
|
21410
|
-
var
|
|
23060
|
+
var ProfileSchema2 = external_exports.object({
|
|
21411
23061
|
project: external_exports.object({
|
|
21412
23062
|
name: external_exports.string().min(1),
|
|
21413
23063
|
repo_url: external_exports.string()
|
|
@@ -21432,7 +23082,7 @@ function buildEventFileName(events, filePath) {
|
|
|
21432
23082
|
return `${lastOccurredAt}-${digest}-${slugify(events[0]?.service.name ?? (0, import_node_path7.basename)(filePath))}.events.json`;
|
|
21433
23083
|
}
|
|
21434
23084
|
async function readProfile(rootDirectory, readFile) {
|
|
21435
|
-
const parsedProfile =
|
|
23085
|
+
const parsedProfile = ProfileSchema2.safeParse(JSON.parse(await readFile((0, import_node_path7.join)(rootDirectory, PROFILE_FILE_PATH))));
|
|
21436
23086
|
if (!parsedProfile.success) {
|
|
21437
23087
|
throw new Error(`Invalid ${PROFILE_FILE_PATH}`);
|
|
21438
23088
|
}
|
|
@@ -21752,19 +23402,32 @@ function formatResult(input, exitCode, checks, errors, incidentId) {
|
|
|
21752
23402
|
output: input.json ? buildJsonOutput(checks, errors, incidentId) : formatHumanOutput(checks, incidentId)
|
|
21753
23403
|
};
|
|
21754
23404
|
}
|
|
21755
|
-
function buildCloudSuggestedActions(status, incidentId,
|
|
23405
|
+
function buildCloudSuggestedActions(status, incidentId, verification) {
|
|
23406
|
+
const mode = verification?.mode ?? "passive_recent_incident";
|
|
21756
23407
|
if (status === "healthy" && incidentId !== void 0 && (mode === "active_5xx" || mode === "active_4xx")) {
|
|
21757
23408
|
return [
|
|
21758
23409
|
`Run debugbundle inspect ${incidentId} --source cloud to inspect why the incident fired.`,
|
|
21759
23410
|
`Run debugbundle bundle ${incidentId} --source cloud to fetch the generated debug bundle.`
|
|
21760
23411
|
];
|
|
21761
23412
|
}
|
|
23413
|
+
if (status === "healthy" && incidentId !== void 0 && mode === "app_event") {
|
|
23414
|
+
return [
|
|
23415
|
+
`Run debugbundle inspect ${incidentId} --source cloud to inspect the captured app event.`,
|
|
23416
|
+
"Re-run debugbundle verify cloud --expect-app-event after instrumentation or deploy changes, using the same service, environment, and correlation hints when available."
|
|
23417
|
+
];
|
|
23418
|
+
}
|
|
21762
23419
|
if (status === "healthy" && incidentId !== void 0) {
|
|
21763
23420
|
return [
|
|
21764
23421
|
`Review incident ${incidentId} if you want to inspect the latest production bundle.`,
|
|
21765
23422
|
"Re-run debugbundle verify cloud after a fresh deploy or instrumentation change."
|
|
21766
23423
|
];
|
|
21767
23424
|
}
|
|
23425
|
+
if (mode === "app_event") {
|
|
23426
|
+
return [
|
|
23427
|
+
"Trigger a real SDK event from the target app, then re-run debugbundle verify cloud --expect-app-event with the same service and environment filters.",
|
|
23428
|
+
"Add --trace-id or --request-id when you have a correlation hint so the verification can match the hosted bundle deterministically."
|
|
23429
|
+
];
|
|
23430
|
+
}
|
|
21768
23431
|
return [
|
|
21769
23432
|
"Run debugbundle login to choose an auth flow, or use debugbundle login --github, debugbundle login --github-device, or debugbundle login <dbundle_mem_...> to create ~/.debugbundle/auth.json before verifying cloud traffic.",
|
|
21770
23433
|
"Generate a live cloud request, then re-run debugbundle verify cloud with the correct project and service filters."
|
|
@@ -21777,7 +23440,7 @@ function buildCloudJsonOutput(checks, errors, incidentId, verification) {
|
|
|
21777
23440
|
checks,
|
|
21778
23441
|
warnings: collectWarnings(checks),
|
|
21779
23442
|
errors,
|
|
21780
|
-
suggested_actions: buildCloudSuggestedActions(status, incidentId, verification
|
|
23443
|
+
suggested_actions: buildCloudSuggestedActions(status, incidentId, verification),
|
|
21781
23444
|
auto_fix_available: false
|
|
21782
23445
|
};
|
|
21783
23446
|
if (verification !== void 0) {
|
|
@@ -21792,7 +23455,7 @@ function formatCloudHumanOutput(checks, incidentId, verification) {
|
|
|
21792
23455
|
"Checks:",
|
|
21793
23456
|
...checks.map((check) => `- ${check.name}: ${check.status} - ${check.message}`),
|
|
21794
23457
|
"Suggested actions:",
|
|
21795
|
-
...buildCloudSuggestedActions(status, incidentId, verification
|
|
23458
|
+
...buildCloudSuggestedActions(status, incidentId, verification).map((action) => `- ${action}`)
|
|
21796
23459
|
].join("\n");
|
|
21797
23460
|
}
|
|
21798
23461
|
function formatCloudResult(input, exitCode, checks, errors, incidentId, verification) {
|
|
@@ -21823,6 +23486,19 @@ function localFailureStepName(checks) {
|
|
|
21823
23486
|
function cloudVerificationRunId(now) {
|
|
21824
23487
|
return now.toISOString().replace(/[-:.TZ]/g, "").slice(0, 14);
|
|
21825
23488
|
}
|
|
23489
|
+
function defaultCloudVerificationSuffix() {
|
|
23490
|
+
return (0, import_node_crypto6.randomUUID)().replace(/-/g, "").slice(0, 12);
|
|
23491
|
+
}
|
|
23492
|
+
function normalizeCloudVerificationSuffix(suffix) {
|
|
23493
|
+
const normalized = suffix.toLowerCase().replace(/[^a-z0-9]/g, "").slice(0, 12);
|
|
23494
|
+
if (normalized.length > 0) {
|
|
23495
|
+
return normalized;
|
|
23496
|
+
}
|
|
23497
|
+
return defaultCloudVerificationSuffix();
|
|
23498
|
+
}
|
|
23499
|
+
function buildCloudVerificationRunId(now, suffix) {
|
|
23500
|
+
return `${cloudVerificationRunId(now)}-${normalizeCloudVerificationSuffix(suffix)}`;
|
|
23501
|
+
}
|
|
21826
23502
|
function requestFailureReason(responseStatus) {
|
|
21827
23503
|
const incidentReason = deriveIncidentReasonFromSignal({
|
|
21828
23504
|
event_type: "request_event",
|
|
@@ -21835,7 +23511,6 @@ function requestFailureReason(responseStatus) {
|
|
|
21835
23511
|
return incidentReason;
|
|
21836
23512
|
}
|
|
21837
23513
|
function buildCloudVerificationEvent(input) {
|
|
21838
|
-
const runId = cloudVerificationRunId(input.now);
|
|
21839
23514
|
const is5xxVerification = input.responseStatus >= 500;
|
|
21840
23515
|
const routeTemplate = is5xxVerification ? "/debugbundle/verify/cloud" : `/debugbundle/verify/cloud/client-error/${input.responseStatus}`;
|
|
21841
23516
|
const verificationLabel = is5xxVerification ? "true" : `client-error-${input.responseStatus}`;
|
|
@@ -21856,7 +23531,7 @@ function buildCloudVerificationEvent(input) {
|
|
|
21856
23531
|
route_template: routeTemplate,
|
|
21857
23532
|
query: {
|
|
21858
23533
|
debugbundle_verification: true,
|
|
21859
|
-
run_id: runId,
|
|
23534
|
+
run_id: input.runId,
|
|
21860
23535
|
synthetic_status: input.responseStatus
|
|
21861
23536
|
},
|
|
21862
23537
|
headers: {
|
|
@@ -21870,7 +23545,7 @@ function buildCloudVerificationEvent(input) {
|
|
|
21870
23545
|
response_body: {
|
|
21871
23546
|
error: is5xxVerification ? "debugbundle_cloud_verification" : "debugbundle_cloud_client_error_verification",
|
|
21872
23547
|
synthetic: true,
|
|
21873
|
-
run_id: runId,
|
|
23548
|
+
run_id: input.runId,
|
|
21874
23549
|
response_status: input.responseStatus
|
|
21875
23550
|
}
|
|
21876
23551
|
}
|
|
@@ -21885,6 +23560,45 @@ function validateActiveCloudVerificationInput(input) {
|
|
|
21885
23560
|
}
|
|
21886
23561
|
return null;
|
|
21887
23562
|
}
|
|
23563
|
+
function validateCloudVerificationInput(input) {
|
|
23564
|
+
const activeInputError = validateActiveCloudVerificationInput(input);
|
|
23565
|
+
if (activeInputError !== null) {
|
|
23566
|
+
return activeInputError;
|
|
23567
|
+
}
|
|
23568
|
+
const appEventVerificationEnabled = input.expectAppEvent === true || input.traceId !== void 0 || input.requestId !== void 0;
|
|
23569
|
+
if (appEventVerificationEnabled && (input.trigger5xx === true || input.trigger4xxStatus !== void 0)) {
|
|
23570
|
+
return "Choose either a synthetic trigger run or --expect-app-event, not both.";
|
|
23571
|
+
}
|
|
23572
|
+
if (appEventVerificationEnabled && input.service === void 0 && input.traceId === void 0 && input.requestId === void 0) {
|
|
23573
|
+
return "App-event verification requires --service, --trace-id, or --request-id so the check stays scoped.";
|
|
23574
|
+
}
|
|
23575
|
+
return null;
|
|
23576
|
+
}
|
|
23577
|
+
function buildCorrelationHints(input) {
|
|
23578
|
+
return {
|
|
23579
|
+
...input.service === void 0 ? {} : { service: input.service },
|
|
23580
|
+
environment: input.environment,
|
|
23581
|
+
...input.traceId === void 0 ? {} : { trace_id: input.traceId },
|
|
23582
|
+
...input.requestId === void 0 ? {} : { request_id: input.requestId }
|
|
23583
|
+
};
|
|
23584
|
+
}
|
|
23585
|
+
function collectBundleHintMatches(bundle, input) {
|
|
23586
|
+
const serializedBundle = JSON.stringify(bundle);
|
|
23587
|
+
const matches = [];
|
|
23588
|
+
if (input.traceId !== void 0 && serializedBundle.includes(input.traceId)) {
|
|
23589
|
+
matches.push("trace_id");
|
|
23590
|
+
}
|
|
23591
|
+
if (input.requestId !== void 0 && serializedBundle.includes(input.requestId)) {
|
|
23592
|
+
matches.push("request_id");
|
|
23593
|
+
}
|
|
23594
|
+
return matches;
|
|
23595
|
+
}
|
|
23596
|
+
function requestedBundleHints(input) {
|
|
23597
|
+
return [
|
|
23598
|
+
...input.traceId === void 0 ? [] : ["trace_id"],
|
|
23599
|
+
...input.requestId === void 0 ? [] : ["request_id"]
|
|
23600
|
+
];
|
|
23601
|
+
}
|
|
21888
23602
|
async function sendEventsToApi(input, dependencies = {}) {
|
|
21889
23603
|
const fetchImpl = dependencies.fetchImpl ?? fetch;
|
|
21890
23604
|
const baseUrl = input.baseUrl.endsWith("/") ? input.baseUrl.slice(0, -1) : input.baseUrl;
|
|
@@ -22076,7 +23790,7 @@ async function verifyCloudCommand(input, dependencies = {}) {
|
|
|
22076
23790
|
const checks = [];
|
|
22077
23791
|
const environment = input.environment ?? "production";
|
|
22078
23792
|
const maxAgeMinutes = input.maxAgeMinutes ?? 15;
|
|
22079
|
-
const activeInputError =
|
|
23793
|
+
const activeInputError = validateCloudVerificationInput(input);
|
|
22080
23794
|
if (activeInputError !== null) {
|
|
22081
23795
|
checks.push({
|
|
22082
23796
|
name: "trigger-input",
|
|
@@ -22103,23 +23817,138 @@ async function verifyCloudCommand(input, dependencies = {}) {
|
|
|
22103
23817
|
});
|
|
22104
23818
|
return formatCloudResult(input, 2, checks, [message]);
|
|
22105
23819
|
}
|
|
22106
|
-
const httpClient = createCliHttpClient(
|
|
22107
|
-
{ baseUrl: authState.base_url },
|
|
22108
|
-
dependencies.fetchImpl === void 0 ? void 0 : { fetchImpl: dependencies.fetchImpl }
|
|
22109
|
-
);
|
|
22110
|
-
const retrievalApi = createRetrievalApi(httpClient);
|
|
22111
|
-
const tokenApi = createTokenManagementApi(httpClient);
|
|
22112
|
-
const listIncidents = dependencies.listIncidents ?? ((requestInput) => retrievalApi.listIncidents(requestInput));
|
|
22113
|
-
const getBundle = dependencies.getBundle ?? ((requestInput) => retrievalApi.getBundle(requestInput));
|
|
22114
|
-
const createProjectToken = dependencies.createProjectToken ?? ((requestInput) => tokenApi.createProjectToken(requestInput));
|
|
22115
|
-
const revokeProjectToken = dependencies.revokeProjectToken ?? ((requestInput) => tokenApi.revokeProjectToken(requestInput));
|
|
22116
|
-
const sendEvents = dependencies.sendEvents ?? ((requestInput) => sendEventsToApi(
|
|
22117
|
-
requestInput,
|
|
22118
|
-
dependencies.fetchImpl === void 0 ? {} : { fetchImpl: dependencies.fetchImpl }
|
|
22119
|
-
));
|
|
23820
|
+
const httpClient = createCliHttpClient(
|
|
23821
|
+
{ baseUrl: authState.base_url },
|
|
23822
|
+
dependencies.fetchImpl === void 0 ? void 0 : { fetchImpl: dependencies.fetchImpl }
|
|
23823
|
+
);
|
|
23824
|
+
const retrievalApi = createRetrievalApi(httpClient);
|
|
23825
|
+
const tokenApi = createTokenManagementApi(httpClient);
|
|
23826
|
+
const listIncidents = dependencies.listIncidents ?? ((requestInput) => retrievalApi.listIncidents(requestInput));
|
|
23827
|
+
const getBundle = dependencies.getBundle ?? ((requestInput) => retrievalApi.getBundle(requestInput));
|
|
23828
|
+
const createProjectToken = dependencies.createProjectToken ?? ((requestInput) => tokenApi.createProjectToken(requestInput));
|
|
23829
|
+
const revokeProjectToken = dependencies.revokeProjectToken ?? ((requestInput) => tokenApi.revokeProjectToken(requestInput));
|
|
23830
|
+
const sendEvents = dependencies.sendEvents ?? ((requestInput) => sendEventsToApi(
|
|
23831
|
+
requestInput,
|
|
23832
|
+
dependencies.fetchImpl === void 0 ? {} : { fetchImpl: dependencies.fetchImpl }
|
|
23833
|
+
));
|
|
23834
|
+
const appEventVerificationEnabled = input.expectAppEvent === true || input.traceId !== void 0 || input.requestId !== void 0;
|
|
23835
|
+
if (appEventVerificationEnabled) {
|
|
23836
|
+
const verificationStartedAt = now();
|
|
23837
|
+
const pollAttempts = dependencies.pollAttempts ?? 6;
|
|
23838
|
+
const pollIntervalMs = dependencies.pollIntervalMs ?? 2e3;
|
|
23839
|
+
const sleep = dependencies.sleep ?? ((milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)));
|
|
23840
|
+
const requestedHints = requestedBundleHints(input);
|
|
23841
|
+
const verification = {
|
|
23842
|
+
mode: "app_event",
|
|
23843
|
+
bundle_status: "unknown",
|
|
23844
|
+
correlation_hints: buildCorrelationHints({
|
|
23845
|
+
environment,
|
|
23846
|
+
...input.service === void 0 ? {} : { service: input.service },
|
|
23847
|
+
...input.traceId === void 0 ? {} : { traceId: input.traceId },
|
|
23848
|
+
...input.requestId === void 0 ? {} : { requestId: input.requestId }
|
|
23849
|
+
})
|
|
23850
|
+
};
|
|
23851
|
+
const oldestAcceptedIncidentTimestamp = verificationStartedAt.getTime() - maxAgeMinutes * 6e4;
|
|
23852
|
+
let incidentId;
|
|
23853
|
+
let exitCode = 0;
|
|
23854
|
+
let activeStep = "app-event-visibility";
|
|
23855
|
+
const errors = [];
|
|
23856
|
+
try {
|
|
23857
|
+
for (let attempt = 1; attempt <= pollAttempts; attempt += 1) {
|
|
23858
|
+
const result = await listIncidents({
|
|
23859
|
+
bearerToken: authState.bearer_token,
|
|
23860
|
+
projectId: input.projectId,
|
|
23861
|
+
environment,
|
|
23862
|
+
...input.service === void 0 ? {} : { service: input.service },
|
|
23863
|
+
limit: 5
|
|
23864
|
+
});
|
|
23865
|
+
const recentIncidents = result.incidents.filter((candidate) => {
|
|
23866
|
+
const lastSeenAt = new Date(candidate.last_seen_at);
|
|
23867
|
+
return !Number.isNaN(lastSeenAt.getTime()) && lastSeenAt.getTime() >= oldestAcceptedIncidentTimestamp;
|
|
23868
|
+
});
|
|
23869
|
+
for (const candidate of recentIncidents) {
|
|
23870
|
+
const lastSeenAt = new Date(candidate.last_seen_at);
|
|
23871
|
+
if (requestedHints.length === 0 && lastSeenAt.getTime() < verificationStartedAt.getTime()) {
|
|
23872
|
+
continue;
|
|
23873
|
+
}
|
|
23874
|
+
if (requestedHints.length === 0) {
|
|
23875
|
+
incidentId = candidate.incident_id;
|
|
23876
|
+
verification.incident_id = candidate.incident_id;
|
|
23877
|
+
break;
|
|
23878
|
+
}
|
|
23879
|
+
activeStep = "bundle-status";
|
|
23880
|
+
const bundle = await getBundle({
|
|
23881
|
+
bearerToken: authState.bearer_token,
|
|
23882
|
+
incidentId: candidate.incident_id
|
|
23883
|
+
});
|
|
23884
|
+
verification.bundle_status = "status" in bundle && bundle.status === "pending" ? "pending" : "ready";
|
|
23885
|
+
if (verification.bundle_status !== "ready") {
|
|
23886
|
+
continue;
|
|
23887
|
+
}
|
|
23888
|
+
const matchedHints = collectBundleHintMatches(bundle, input);
|
|
23889
|
+
verification.matched_hints = matchedHints;
|
|
23890
|
+
if (requestedHints.every((hint) => matchedHints.includes(hint))) {
|
|
23891
|
+
incidentId = candidate.incident_id;
|
|
23892
|
+
verification.incident_id = candidate.incident_id;
|
|
23893
|
+
verification.suggested_next_command = `debugbundle inspect ${candidate.incident_id} --source cloud`;
|
|
23894
|
+
break;
|
|
23895
|
+
}
|
|
23896
|
+
}
|
|
23897
|
+
if (incidentId !== void 0) {
|
|
23898
|
+
break;
|
|
23899
|
+
}
|
|
23900
|
+
if (attempt < pollAttempts) {
|
|
23901
|
+
await sleep(pollIntervalMs);
|
|
23902
|
+
}
|
|
23903
|
+
}
|
|
23904
|
+
if (incidentId === void 0) {
|
|
23905
|
+
if (requestedHints.length > 0) {
|
|
23906
|
+
throw new Error(`No recent cloud incident matched the requested ${requestedHints.join(" and ")} hints within the ${maxAgeMinutes} minute verification window.`);
|
|
23907
|
+
}
|
|
23908
|
+
throw new Error(`No new ${environment} app event was visible within the ${maxAgeMinutes} minute verification window.`);
|
|
23909
|
+
}
|
|
23910
|
+
checks.push({
|
|
23911
|
+
name: "app-event-visibility",
|
|
23912
|
+
status: "ok",
|
|
23913
|
+
message: `Observed cloud incident ${incidentId} for the requested app-driven verification window.`
|
|
23914
|
+
});
|
|
23915
|
+
if (requestedHints.length > 0) {
|
|
23916
|
+
checks.push({
|
|
23917
|
+
name: "bundle-hint-match",
|
|
23918
|
+
status: "ok",
|
|
23919
|
+
message: `Matched ${verification.matched_hints?.join(" and ")} in bundle ${incidentId}.`
|
|
23920
|
+
});
|
|
23921
|
+
} else {
|
|
23922
|
+
const bundle = await getBundle({
|
|
23923
|
+
bearerToken: authState.bearer_token,
|
|
23924
|
+
incidentId
|
|
23925
|
+
});
|
|
23926
|
+
verification.bundle_status = "status" in bundle && bundle.status === "pending" ? "pending" : "ready";
|
|
23927
|
+
verification.suggested_next_command = `debugbundle inspect ${incidentId} --source cloud`;
|
|
23928
|
+
checks.push({
|
|
23929
|
+
name: "bundle-status",
|
|
23930
|
+
status: verification.bundle_status === "ready" ? "ok" : "warning",
|
|
23931
|
+
message: verification.bundle_status === "ready" ? `Bundle for incident ${incidentId} is ready.` : `Bundle for incident ${incidentId} is still pending.`
|
|
23932
|
+
});
|
|
23933
|
+
}
|
|
23934
|
+
} catch (error) {
|
|
23935
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
23936
|
+
checks.push({
|
|
23937
|
+
name: activeStep,
|
|
23938
|
+
status: "error",
|
|
23939
|
+
message
|
|
23940
|
+
});
|
|
23941
|
+
errors.push(message);
|
|
23942
|
+
exitCode = 1;
|
|
23943
|
+
}
|
|
23944
|
+
return formatCloudResult(input, exitCode, checks, errors, incidentId, verification);
|
|
23945
|
+
}
|
|
22120
23946
|
if (input.trigger5xx === true || input.trigger4xxStatus !== void 0) {
|
|
22121
23947
|
const verificationStartedAt = now();
|
|
22122
|
-
const runId =
|
|
23948
|
+
const runId = buildCloudVerificationRunId(
|
|
23949
|
+
verificationStartedAt,
|
|
23950
|
+
(dependencies.randomId ?? defaultCloudVerificationSuffix)()
|
|
23951
|
+
);
|
|
22123
23952
|
const serviceName = input.service ?? `debugbundle-verify-cloud-${runId}`;
|
|
22124
23953
|
const tokenLabel = `debugbundle verify cloud ${runId}`;
|
|
22125
23954
|
const pollAttempts = dependencies.pollAttempts ?? 6;
|
|
@@ -22151,6 +23980,7 @@ async function verifyCloudCommand(input, dependencies = {}) {
|
|
|
22151
23980
|
}
|
|
22152
23981
|
const event = buildCloudVerificationEvent({
|
|
22153
23982
|
now: verificationStartedAt,
|
|
23983
|
+
runId,
|
|
22154
23984
|
serviceName,
|
|
22155
23985
|
environment,
|
|
22156
23986
|
responseStatus
|
|
@@ -22870,8 +24700,85 @@ function createBillingMcpTools(api) {
|
|
|
22870
24700
|
};
|
|
22871
24701
|
}
|
|
22872
24702
|
|
|
22873
|
-
// src/capture-
|
|
24703
|
+
// src/capture-rule-tools.ts
|
|
22874
24704
|
function mapMcpError4(error) {
|
|
24705
|
+
if (error instanceof CaptureRuleApiError) {
|
|
24706
|
+
throw new Error(`mcp_tool_error:${error.message}`);
|
|
24707
|
+
}
|
|
24708
|
+
throw new Error("mcp_tool_error:unknown_error");
|
|
24709
|
+
}
|
|
24710
|
+
function createCaptureRuleMcpTools(api) {
|
|
24711
|
+
return {
|
|
24712
|
+
async list_capture_rules(input) {
|
|
24713
|
+
try {
|
|
24714
|
+
return await api.listCaptureRules({
|
|
24715
|
+
bearerToken: String(input["bearerToken"]),
|
|
24716
|
+
projectId: String(input["projectId"])
|
|
24717
|
+
});
|
|
24718
|
+
} catch (error) {
|
|
24719
|
+
mapMcpError4(error);
|
|
24720
|
+
}
|
|
24721
|
+
},
|
|
24722
|
+
async create_capture_rule(input) {
|
|
24723
|
+
try {
|
|
24724
|
+
return await api.createCaptureRule({
|
|
24725
|
+
bearerToken: String(input["bearerToken"]),
|
|
24726
|
+
projectId: String(input["projectId"]),
|
|
24727
|
+
create: typeof input["create"] === "object" && input["create"] !== null ? input["create"] : {}
|
|
24728
|
+
});
|
|
24729
|
+
} catch (error) {
|
|
24730
|
+
mapMcpError4(error);
|
|
24731
|
+
}
|
|
24732
|
+
},
|
|
24733
|
+
async update_capture_rule(input) {
|
|
24734
|
+
try {
|
|
24735
|
+
return await api.updateCaptureRule({
|
|
24736
|
+
bearerToken: String(input["bearerToken"]),
|
|
24737
|
+
projectId: String(input["projectId"]),
|
|
24738
|
+
ruleId: String(input["ruleId"]),
|
|
24739
|
+
update: typeof input["update"] === "object" && input["update"] !== null ? input["update"] : {}
|
|
24740
|
+
});
|
|
24741
|
+
} catch (error) {
|
|
24742
|
+
mapMcpError4(error);
|
|
24743
|
+
}
|
|
24744
|
+
},
|
|
24745
|
+
async delete_capture_rule(input) {
|
|
24746
|
+
try {
|
|
24747
|
+
return await api.deleteCaptureRule({
|
|
24748
|
+
bearerToken: String(input["bearerToken"]),
|
|
24749
|
+
projectId: String(input["projectId"]),
|
|
24750
|
+
ruleId: String(input["ruleId"])
|
|
24751
|
+
});
|
|
24752
|
+
} catch (error) {
|
|
24753
|
+
mapMcpError4(error);
|
|
24754
|
+
}
|
|
24755
|
+
},
|
|
24756
|
+
async suggest_capture_rules_from_incident(input) {
|
|
24757
|
+
try {
|
|
24758
|
+
return await api.suggestCaptureRulesFromIncident({
|
|
24759
|
+
bearerToken: String(input["bearerToken"]),
|
|
24760
|
+
incidentId: String(input["incidentId"])
|
|
24761
|
+
});
|
|
24762
|
+
} catch (error) {
|
|
24763
|
+
mapMcpError4(error);
|
|
24764
|
+
}
|
|
24765
|
+
},
|
|
24766
|
+
async create_capture_rule_from_incident_suggestion(input) {
|
|
24767
|
+
try {
|
|
24768
|
+
return await api.createCaptureRuleFromIncidentSuggestion({
|
|
24769
|
+
bearerToken: String(input["bearerToken"]),
|
|
24770
|
+
incidentId: String(input["incidentId"]),
|
|
24771
|
+
create: typeof input["create"] === "object" && input["create"] !== null ? input["create"] : {}
|
|
24772
|
+
});
|
|
24773
|
+
} catch (error) {
|
|
24774
|
+
mapMcpError4(error);
|
|
24775
|
+
}
|
|
24776
|
+
}
|
|
24777
|
+
};
|
|
24778
|
+
}
|
|
24779
|
+
|
|
24780
|
+
// src/capture-policy-tools.ts
|
|
24781
|
+
function mapMcpError5(error) {
|
|
22875
24782
|
if (error instanceof CapturePolicyApiError) {
|
|
22876
24783
|
throw new Error(`mcp_tool_error:${error.message}`);
|
|
22877
24784
|
}
|
|
@@ -22886,7 +24793,7 @@ function createCapturePolicyMcpTools(api) {
|
|
|
22886
24793
|
projectId: String(input["projectId"])
|
|
22887
24794
|
});
|
|
22888
24795
|
} catch (error) {
|
|
22889
|
-
|
|
24796
|
+
mapMcpError5(error);
|
|
22890
24797
|
}
|
|
22891
24798
|
},
|
|
22892
24799
|
async update_capture_policy(input) {
|
|
@@ -22898,14 +24805,14 @@ function createCapturePolicyMcpTools(api) {
|
|
|
22898
24805
|
update
|
|
22899
24806
|
});
|
|
22900
24807
|
} catch (error) {
|
|
22901
|
-
|
|
24808
|
+
mapMcpError5(error);
|
|
22902
24809
|
}
|
|
22903
24810
|
}
|
|
22904
24811
|
};
|
|
22905
24812
|
}
|
|
22906
24813
|
|
|
22907
24814
|
// src/github-tools.ts
|
|
22908
|
-
function
|
|
24815
|
+
function mapMcpError6(error) {
|
|
22909
24816
|
if (error instanceof GitHubManagementApiError) {
|
|
22910
24817
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
22911
24818
|
}
|
|
@@ -22924,7 +24831,7 @@ function createGitHubMcpTools(api) {
|
|
|
22924
24831
|
const repo = projectId === void 0 || api.getProjectRepo === void 0 ? void 0 : await api.getProjectRepo({ bearerToken, projectId });
|
|
22925
24832
|
return repo === void 0 ? { installation } : { installation, repo };
|
|
22926
24833
|
} catch (error) {
|
|
22927
|
-
|
|
24834
|
+
mapMcpError6(error);
|
|
22928
24835
|
}
|
|
22929
24836
|
},
|
|
22930
24837
|
async list_github_repositories(input) {
|
|
@@ -22936,7 +24843,7 @@ function createGitHubMcpTools(api) {
|
|
|
22936
24843
|
})
|
|
22937
24844
|
};
|
|
22938
24845
|
} catch (error) {
|
|
22939
|
-
|
|
24846
|
+
mapMcpError6(error);
|
|
22940
24847
|
}
|
|
22941
24848
|
},
|
|
22942
24849
|
async list_github_dispatch_rules(input) {
|
|
@@ -22948,7 +24855,7 @@ function createGitHubMcpTools(api) {
|
|
|
22948
24855
|
})
|
|
22949
24856
|
};
|
|
22950
24857
|
} catch (error) {
|
|
22951
|
-
|
|
24858
|
+
mapMcpError6(error);
|
|
22952
24859
|
}
|
|
22953
24860
|
},
|
|
22954
24861
|
async create_github_dispatch_rule(input) {
|
|
@@ -22969,7 +24876,7 @@ function createGitHubMcpTools(api) {
|
|
|
22969
24876
|
})
|
|
22970
24877
|
};
|
|
22971
24878
|
} catch (error) {
|
|
22972
|
-
|
|
24879
|
+
mapMcpError6(error);
|
|
22973
24880
|
}
|
|
22974
24881
|
},
|
|
22975
24882
|
async update_github_dispatch_rule(input) {
|
|
@@ -22991,7 +24898,7 @@ function createGitHubMcpTools(api) {
|
|
|
22991
24898
|
})
|
|
22992
24899
|
};
|
|
22993
24900
|
} catch (error) {
|
|
22994
|
-
|
|
24901
|
+
mapMcpError6(error);
|
|
22995
24902
|
}
|
|
22996
24903
|
},
|
|
22997
24904
|
async delete_github_dispatch_rule(input) {
|
|
@@ -23007,7 +24914,7 @@ function createGitHubMcpTools(api) {
|
|
|
23007
24914
|
rule_id: String(input["ruleId"])
|
|
23008
24915
|
};
|
|
23009
24916
|
} catch (error) {
|
|
23010
|
-
|
|
24917
|
+
mapMcpError6(error);
|
|
23011
24918
|
}
|
|
23012
24919
|
},
|
|
23013
24920
|
async list_github_deliveries(input) {
|
|
@@ -23021,7 +24928,7 @@ function createGitHubMcpTools(api) {
|
|
|
23021
24928
|
})
|
|
23022
24929
|
};
|
|
23023
24930
|
} catch (error) {
|
|
23024
|
-
|
|
24931
|
+
mapMcpError6(error);
|
|
23025
24932
|
}
|
|
23026
24933
|
},
|
|
23027
24934
|
async retry_github_delivery(input) {
|
|
@@ -23034,7 +24941,7 @@ function createGitHubMcpTools(api) {
|
|
|
23034
24941
|
})
|
|
23035
24942
|
};
|
|
23036
24943
|
} catch (error) {
|
|
23037
|
-
|
|
24944
|
+
mapMcpError6(error);
|
|
23038
24945
|
}
|
|
23039
24946
|
},
|
|
23040
24947
|
async set_project_github_repo(input) {
|
|
@@ -23048,7 +24955,7 @@ function createGitHubMcpTools(api) {
|
|
|
23048
24955
|
})
|
|
23049
24956
|
};
|
|
23050
24957
|
} catch (error) {
|
|
23051
|
-
|
|
24958
|
+
mapMcpError6(error);
|
|
23052
24959
|
}
|
|
23053
24960
|
},
|
|
23054
24961
|
async remove_project_github_repo(input) {
|
|
@@ -23062,14 +24969,14 @@ function createGitHubMcpTools(api) {
|
|
|
23062
24969
|
project_id: String(input["projectId"])
|
|
23063
24970
|
};
|
|
23064
24971
|
} catch (error) {
|
|
23065
|
-
|
|
24972
|
+
mapMcpError6(error);
|
|
23066
24973
|
}
|
|
23067
24974
|
}
|
|
23068
24975
|
};
|
|
23069
24976
|
}
|
|
23070
24977
|
|
|
23071
24978
|
// src/improvement-tools.ts
|
|
23072
|
-
function
|
|
24979
|
+
function mapMcpError7(error) {
|
|
23073
24980
|
if (error instanceof RetrievalApiError) {
|
|
23074
24981
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
23075
24982
|
}
|
|
@@ -23102,7 +25009,7 @@ function createImprovementMcpTools(api) {
|
|
|
23102
25009
|
...typeof input["limit"] === "number" ? { limit: input["limit"] } : {}
|
|
23103
25010
|
});
|
|
23104
25011
|
} catch (error) {
|
|
23105
|
-
|
|
25012
|
+
mapMcpError7(error);
|
|
23106
25013
|
}
|
|
23107
25014
|
},
|
|
23108
25015
|
async get_improvement(input) {
|
|
@@ -23112,7 +25019,7 @@ function createImprovementMcpTools(api) {
|
|
|
23112
25019
|
improvementId: readString2(input, "improvementId")
|
|
23113
25020
|
});
|
|
23114
25021
|
} catch (error) {
|
|
23115
|
-
|
|
25022
|
+
mapMcpError7(error);
|
|
23116
25023
|
}
|
|
23117
25024
|
},
|
|
23118
25025
|
async get_improvement_bundle(input) {
|
|
@@ -23123,7 +25030,7 @@ function createImprovementMcpTools(api) {
|
|
|
23123
25030
|
improvementId: readString2(input, "improvementId")
|
|
23124
25031
|
});
|
|
23125
25032
|
} catch (error) {
|
|
23126
|
-
|
|
25033
|
+
mapMcpError7(error);
|
|
23127
25034
|
}
|
|
23128
25035
|
},
|
|
23129
25036
|
async resolve_improvement(input) {
|
|
@@ -23133,7 +25040,7 @@ function createImprovementMcpTools(api) {
|
|
|
23133
25040
|
improvementId: readString2(input, "improvementId")
|
|
23134
25041
|
});
|
|
23135
25042
|
} catch (error) {
|
|
23136
|
-
|
|
25043
|
+
mapMcpError7(error);
|
|
23137
25044
|
}
|
|
23138
25045
|
},
|
|
23139
25046
|
async reopen_improvement(input) {
|
|
@@ -23143,7 +25050,7 @@ function createImprovementMcpTools(api) {
|
|
|
23143
25050
|
improvementId: readString2(input, "improvementId")
|
|
23144
25051
|
});
|
|
23145
25052
|
} catch (error) {
|
|
23146
|
-
|
|
25053
|
+
mapMcpError7(error);
|
|
23147
25054
|
}
|
|
23148
25055
|
},
|
|
23149
25056
|
async snooze_improvement(input) {
|
|
@@ -23154,14 +25061,14 @@ function createImprovementMcpTools(api) {
|
|
|
23154
25061
|
snoozedUntil: readString2(input, "snoozedUntil")
|
|
23155
25062
|
});
|
|
23156
25063
|
} catch (error) {
|
|
23157
|
-
|
|
25064
|
+
mapMcpError7(error);
|
|
23158
25065
|
}
|
|
23159
25066
|
}
|
|
23160
25067
|
};
|
|
23161
25068
|
}
|
|
23162
25069
|
|
|
23163
25070
|
// src/improvement-settings-tools.ts
|
|
23164
|
-
function
|
|
25071
|
+
function mapMcpError8(error) {
|
|
23165
25072
|
if (error instanceof ImprovementSettingsApiError) {
|
|
23166
25073
|
throw new Error(`mcp_tool_error:${error.message}`);
|
|
23167
25074
|
}
|
|
@@ -23176,7 +25083,7 @@ function createImprovementSettingsMcpTools(api) {
|
|
|
23176
25083
|
projectId: String(input["projectId"])
|
|
23177
25084
|
});
|
|
23178
25085
|
} catch (error) {
|
|
23179
|
-
|
|
25086
|
+
mapMcpError8(error);
|
|
23180
25087
|
}
|
|
23181
25088
|
},
|
|
23182
25089
|
async update_improvement_settings(input) {
|
|
@@ -23188,14 +25095,14 @@ function createImprovementSettingsMcpTools(api) {
|
|
|
23188
25095
|
update
|
|
23189
25096
|
});
|
|
23190
25097
|
} catch (error) {
|
|
23191
|
-
|
|
25098
|
+
mapMcpError8(error);
|
|
23192
25099
|
}
|
|
23193
25100
|
}
|
|
23194
25101
|
};
|
|
23195
25102
|
}
|
|
23196
25103
|
|
|
23197
25104
|
// src/member-tools.ts
|
|
23198
|
-
function
|
|
25105
|
+
function mapMcpError9(error) {
|
|
23199
25106
|
if (error instanceof MemberApiError) {
|
|
23200
25107
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
23201
25108
|
}
|
|
@@ -23210,7 +25117,7 @@ function createMemberMcpTools(api) {
|
|
|
23210
25117
|
projectId: String(input["projectId"])
|
|
23211
25118
|
});
|
|
23212
25119
|
} catch (error) {
|
|
23213
|
-
|
|
25120
|
+
mapMcpError9(error);
|
|
23214
25121
|
}
|
|
23215
25122
|
},
|
|
23216
25123
|
async list_project_member_invites(input) {
|
|
@@ -23220,7 +25127,7 @@ function createMemberMcpTools(api) {
|
|
|
23220
25127
|
projectId: String(input["projectId"])
|
|
23221
25128
|
});
|
|
23222
25129
|
} catch (error) {
|
|
23223
|
-
|
|
25130
|
+
mapMcpError9(error);
|
|
23224
25131
|
}
|
|
23225
25132
|
},
|
|
23226
25133
|
async invite_project_member(input) {
|
|
@@ -23232,7 +25139,7 @@ function createMemberMcpTools(api) {
|
|
|
23232
25139
|
role: String(input["role"])
|
|
23233
25140
|
});
|
|
23234
25141
|
} catch (error) {
|
|
23235
|
-
|
|
25142
|
+
mapMcpError9(error);
|
|
23236
25143
|
}
|
|
23237
25144
|
},
|
|
23238
25145
|
async cancel_project_member_invite(input) {
|
|
@@ -23243,7 +25150,7 @@ function createMemberMcpTools(api) {
|
|
|
23243
25150
|
inviteId: String(input["inviteId"])
|
|
23244
25151
|
});
|
|
23245
25152
|
} catch (error) {
|
|
23246
|
-
|
|
25153
|
+
mapMcpError9(error);
|
|
23247
25154
|
}
|
|
23248
25155
|
},
|
|
23249
25156
|
async update_project_member_role(input) {
|
|
@@ -23255,7 +25162,7 @@ function createMemberMcpTools(api) {
|
|
|
23255
25162
|
role: String(input["role"])
|
|
23256
25163
|
});
|
|
23257
25164
|
} catch (error) {
|
|
23258
|
-
|
|
25165
|
+
mapMcpError9(error);
|
|
23259
25166
|
}
|
|
23260
25167
|
},
|
|
23261
25168
|
async remove_project_member(input) {
|
|
@@ -23266,14 +25173,14 @@ function createMemberMcpTools(api) {
|
|
|
23266
25173
|
userId: String(input["userId"])
|
|
23267
25174
|
});
|
|
23268
25175
|
} catch (error) {
|
|
23269
|
-
|
|
25176
|
+
mapMcpError9(error);
|
|
23270
25177
|
}
|
|
23271
25178
|
}
|
|
23272
25179
|
};
|
|
23273
25180
|
}
|
|
23274
25181
|
|
|
23275
25182
|
// src/probe-tools.ts
|
|
23276
|
-
function
|
|
25183
|
+
function mapMcpError10(error) {
|
|
23277
25184
|
if (error instanceof ProbeApiError) {
|
|
23278
25185
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
23279
25186
|
}
|
|
@@ -23302,7 +25209,7 @@ function createProbeMcpTools(api) {
|
|
|
23302
25209
|
}
|
|
23303
25210
|
return await api.activateProbe(requestInput);
|
|
23304
25211
|
} catch (error) {
|
|
23305
|
-
|
|
25212
|
+
mapMcpError10(error);
|
|
23306
25213
|
}
|
|
23307
25214
|
},
|
|
23308
25215
|
async list_active_probes(input) {
|
|
@@ -23312,7 +25219,7 @@ function createProbeMcpTools(api) {
|
|
|
23312
25219
|
projectId: String(input["projectId"])
|
|
23313
25220
|
});
|
|
23314
25221
|
} catch (error) {
|
|
23315
|
-
|
|
25222
|
+
mapMcpError10(error);
|
|
23316
25223
|
}
|
|
23317
25224
|
},
|
|
23318
25225
|
async deactivate_probe(input) {
|
|
@@ -23323,14 +25230,14 @@ function createProbeMcpTools(api) {
|
|
|
23323
25230
|
activationId: String(input["activationId"])
|
|
23324
25231
|
});
|
|
23325
25232
|
} catch (error) {
|
|
23326
|
-
|
|
25233
|
+
mapMcpError10(error);
|
|
23327
25234
|
}
|
|
23328
25235
|
}
|
|
23329
25236
|
};
|
|
23330
25237
|
}
|
|
23331
25238
|
|
|
23332
25239
|
// src/project-tools.ts
|
|
23333
|
-
function
|
|
25240
|
+
function mapMcpError11(error) {
|
|
23334
25241
|
if (error instanceof ProjectManagementApiError) {
|
|
23335
25242
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
23336
25243
|
}
|
|
@@ -23348,7 +25255,7 @@ function createProjectMcpTools(api) {
|
|
|
23348
25255
|
}
|
|
23349
25256
|
return { projects: await api.listProjects(requestInput) };
|
|
23350
25257
|
} catch (error) {
|
|
23351
|
-
|
|
25258
|
+
mapMcpError11(error);
|
|
23352
25259
|
}
|
|
23353
25260
|
},
|
|
23354
25261
|
async create_project(input) {
|
|
@@ -23363,7 +25270,7 @@ function createProjectMcpTools(api) {
|
|
|
23363
25270
|
}
|
|
23364
25271
|
return { project: await api.createProject(requestInput) };
|
|
23365
25272
|
} catch (error) {
|
|
23366
|
-
|
|
25273
|
+
mapMcpError11(error);
|
|
23367
25274
|
}
|
|
23368
25275
|
},
|
|
23369
25276
|
async update_project(input) {
|
|
@@ -23383,7 +25290,7 @@ function createProjectMcpTools(api) {
|
|
|
23383
25290
|
}
|
|
23384
25291
|
return { project: await api.updateProject(requestInput) };
|
|
23385
25292
|
} catch (error) {
|
|
23386
|
-
|
|
25293
|
+
mapMcpError11(error);
|
|
23387
25294
|
}
|
|
23388
25295
|
},
|
|
23389
25296
|
async delete_project(input) {
|
|
@@ -23395,7 +25302,7 @@ function createProjectMcpTools(api) {
|
|
|
23395
25302
|
})
|
|
23396
25303
|
};
|
|
23397
25304
|
} catch (error) {
|
|
23398
|
-
|
|
25305
|
+
mapMcpError11(error);
|
|
23399
25306
|
}
|
|
23400
25307
|
}
|
|
23401
25308
|
};
|
|
@@ -23602,7 +25509,7 @@ async function persistCloudArtifact(directoryPath, fileName, payload, dependenci
|
|
|
23602
25509
|
}
|
|
23603
25510
|
|
|
23604
25511
|
// src/retrieval-tools.ts
|
|
23605
|
-
function
|
|
25512
|
+
function mapMcpError12(error) {
|
|
23606
25513
|
if (error instanceof RetrievalApiError) {
|
|
23607
25514
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
23608
25515
|
}
|
|
@@ -23784,7 +25691,7 @@ function createRetrievalMcpTools(api) {
|
|
|
23784
25691
|
incidents: incidents.incidents.map((incident) => attachSourceToRecord(incident, "cloud"))
|
|
23785
25692
|
};
|
|
23786
25693
|
} catch (error) {
|
|
23787
|
-
|
|
25694
|
+
mapMcpError12(error);
|
|
23788
25695
|
}
|
|
23789
25696
|
},
|
|
23790
25697
|
async get_incident(input) {
|
|
@@ -23819,7 +25726,7 @@ function createRetrievalMcpTools(api) {
|
|
|
23819
25726
|
)
|
|
23820
25727
|
};
|
|
23821
25728
|
} catch (error) {
|
|
23822
|
-
|
|
25729
|
+
mapMcpError12(error);
|
|
23823
25730
|
}
|
|
23824
25731
|
},
|
|
23825
25732
|
async get_incident_context(input) {
|
|
@@ -23848,7 +25755,7 @@ function createRetrievalMcpTools(api) {
|
|
|
23848
25755
|
"cloud"
|
|
23849
25756
|
);
|
|
23850
25757
|
} catch (error) {
|
|
23851
|
-
|
|
25758
|
+
mapMcpError12(error);
|
|
23852
25759
|
}
|
|
23853
25760
|
},
|
|
23854
25761
|
async resolve_incident(input) {
|
|
@@ -23893,7 +25800,7 @@ function createRetrievalMcpTools(api) {
|
|
|
23893
25800
|
})()
|
|
23894
25801
|
};
|
|
23895
25802
|
} catch (error) {
|
|
23896
|
-
|
|
25803
|
+
mapMcpError12(error);
|
|
23897
25804
|
}
|
|
23898
25805
|
},
|
|
23899
25806
|
async reopen_incident(input) {
|
|
@@ -23938,7 +25845,7 @@ function createRetrievalMcpTools(api) {
|
|
|
23938
25845
|
})()
|
|
23939
25846
|
};
|
|
23940
25847
|
} catch (error) {
|
|
23941
|
-
|
|
25848
|
+
mapMcpError12(error);
|
|
23942
25849
|
}
|
|
23943
25850
|
},
|
|
23944
25851
|
async get_bundle(input) {
|
|
@@ -23969,7 +25876,7 @@ function createRetrievalMcpTools(api) {
|
|
|
23969
25876
|
}
|
|
23970
25877
|
);
|
|
23971
25878
|
} catch (error) {
|
|
23972
|
-
|
|
25879
|
+
mapMcpError12(error);
|
|
23973
25880
|
}
|
|
23974
25881
|
},
|
|
23975
25882
|
async get_logs(input) {
|
|
@@ -23989,7 +25896,7 @@ function createRetrievalMcpTools(api) {
|
|
|
23989
25896
|
}
|
|
23990
25897
|
return await api.getLogs(requestInput);
|
|
23991
25898
|
} catch (error) {
|
|
23992
|
-
|
|
25899
|
+
mapMcpError12(error);
|
|
23993
25900
|
}
|
|
23994
25901
|
},
|
|
23995
25902
|
async get_reproduction(input) {
|
|
@@ -24020,14 +25927,14 @@ function createRetrievalMcpTools(api) {
|
|
|
24020
25927
|
}
|
|
24021
25928
|
);
|
|
24022
25929
|
} catch (error) {
|
|
24023
|
-
|
|
25930
|
+
mapMcpError12(error);
|
|
24024
25931
|
}
|
|
24025
25932
|
}
|
|
24026
25933
|
};
|
|
24027
25934
|
}
|
|
24028
25935
|
|
|
24029
25936
|
// src/services-tools.ts
|
|
24030
|
-
function
|
|
25937
|
+
function mapMcpError13(error) {
|
|
24031
25938
|
if (error instanceof RetrievalApiError) {
|
|
24032
25939
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
24033
25940
|
}
|
|
@@ -24048,14 +25955,14 @@ function createServicesMcpTools(api) {
|
|
|
24048
25955
|
services: await api.listServices(requestInput)
|
|
24049
25956
|
};
|
|
24050
25957
|
} catch (error) {
|
|
24051
|
-
|
|
25958
|
+
mapMcpError13(error);
|
|
24052
25959
|
}
|
|
24053
25960
|
}
|
|
24054
25961
|
};
|
|
24055
25962
|
}
|
|
24056
25963
|
|
|
24057
25964
|
// src/setup-tools.ts
|
|
24058
|
-
function
|
|
25965
|
+
function mapMcpError14() {
|
|
24059
25966
|
throw new Error("mcp_tool_error:unknown_error");
|
|
24060
25967
|
}
|
|
24061
25968
|
function parseJsonOutput2(output) {
|
|
@@ -24070,7 +25977,7 @@ async function runJsonCommand2(command) {
|
|
|
24070
25977
|
const result = await command();
|
|
24071
25978
|
return parseJsonOutput2(result.output);
|
|
24072
25979
|
} catch {
|
|
24073
|
-
|
|
25980
|
+
mapMcpError14();
|
|
24074
25981
|
}
|
|
24075
25982
|
}
|
|
24076
25983
|
function createSetupMcpTools(commands) {
|
|
@@ -24129,7 +26036,7 @@ function createSetupMcpTools(commands) {
|
|
|
24129
26036
|
}
|
|
24130
26037
|
|
|
24131
26038
|
// src/slack-tools.ts
|
|
24132
|
-
function
|
|
26039
|
+
function mapMcpError15(error) {
|
|
24133
26040
|
if (error instanceof SlackApiError) {
|
|
24134
26041
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
24135
26042
|
}
|
|
@@ -24146,7 +26053,7 @@ function createSlackMcpTools(api) {
|
|
|
24146
26053
|
})
|
|
24147
26054
|
};
|
|
24148
26055
|
} catch (error) {
|
|
24149
|
-
|
|
26056
|
+
mapMcpError15(error);
|
|
24150
26057
|
}
|
|
24151
26058
|
},
|
|
24152
26059
|
async get_slack_connect_url(input) {
|
|
@@ -24159,7 +26066,7 @@ function createSlackMcpTools(api) {
|
|
|
24159
26066
|
})
|
|
24160
26067
|
};
|
|
24161
26068
|
} catch (error) {
|
|
24162
|
-
|
|
26069
|
+
mapMcpError15(error);
|
|
24163
26070
|
}
|
|
24164
26071
|
},
|
|
24165
26072
|
async test_slack_destination(input) {
|
|
@@ -24172,7 +26079,7 @@ function createSlackMcpTools(api) {
|
|
|
24172
26079
|
})
|
|
24173
26080
|
};
|
|
24174
26081
|
} catch (error) {
|
|
24175
|
-
|
|
26082
|
+
mapMcpError15(error);
|
|
24176
26083
|
}
|
|
24177
26084
|
},
|
|
24178
26085
|
async delete_slack_destination(input) {
|
|
@@ -24185,14 +26092,14 @@ function createSlackMcpTools(api) {
|
|
|
24185
26092
|
})
|
|
24186
26093
|
};
|
|
24187
26094
|
} catch (error) {
|
|
24188
|
-
|
|
26095
|
+
mapMcpError15(error);
|
|
24189
26096
|
}
|
|
24190
26097
|
}
|
|
24191
26098
|
};
|
|
24192
26099
|
}
|
|
24193
26100
|
|
|
24194
26101
|
// src/token-tools.ts
|
|
24195
|
-
function
|
|
26102
|
+
function mapMcpError16(error) {
|
|
24196
26103
|
if (error instanceof TokenManagementApiError) {
|
|
24197
26104
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
24198
26105
|
}
|
|
@@ -24213,7 +26120,7 @@ function createTokenMcpTools(api) {
|
|
|
24213
26120
|
tokens: await api.listProjectTokens(requestInput)
|
|
24214
26121
|
};
|
|
24215
26122
|
} catch (error) {
|
|
24216
|
-
|
|
26123
|
+
mapMcpError16(error);
|
|
24217
26124
|
}
|
|
24218
26125
|
},
|
|
24219
26126
|
async create_project_token(input) {
|
|
@@ -24228,7 +26135,7 @@ function createTokenMcpTools(api) {
|
|
|
24228
26135
|
})
|
|
24229
26136
|
};
|
|
24230
26137
|
} catch (error) {
|
|
24231
|
-
|
|
26138
|
+
mapMcpError16(error);
|
|
24232
26139
|
}
|
|
24233
26140
|
},
|
|
24234
26141
|
async revoke_project_token(input) {
|
|
@@ -24241,7 +26148,7 @@ function createTokenMcpTools(api) {
|
|
|
24241
26148
|
})
|
|
24242
26149
|
};
|
|
24243
26150
|
} catch (error) {
|
|
24244
|
-
|
|
26151
|
+
mapMcpError16(error);
|
|
24245
26152
|
}
|
|
24246
26153
|
},
|
|
24247
26154
|
async list_member_tokens(input) {
|
|
@@ -24256,7 +26163,7 @@ function createTokenMcpTools(api) {
|
|
|
24256
26163
|
tokens: await api.listMemberTokens(requestInput)
|
|
24257
26164
|
};
|
|
24258
26165
|
} catch (error) {
|
|
24259
|
-
|
|
26166
|
+
mapMcpError16(error);
|
|
24260
26167
|
}
|
|
24261
26168
|
},
|
|
24262
26169
|
async create_member_token(input) {
|
|
@@ -24268,7 +26175,7 @@ function createTokenMcpTools(api) {
|
|
|
24268
26175
|
})
|
|
24269
26176
|
};
|
|
24270
26177
|
} catch (error) {
|
|
24271
|
-
|
|
26178
|
+
mapMcpError16(error);
|
|
24272
26179
|
}
|
|
24273
26180
|
},
|
|
24274
26181
|
async revoke_member_token(input) {
|
|
@@ -24280,14 +26187,14 @@ function createTokenMcpTools(api) {
|
|
|
24280
26187
|
})
|
|
24281
26188
|
};
|
|
24282
26189
|
} catch (error) {
|
|
24283
|
-
|
|
26190
|
+
mapMcpError16(error);
|
|
24284
26191
|
}
|
|
24285
26192
|
}
|
|
24286
26193
|
};
|
|
24287
26194
|
}
|
|
24288
26195
|
|
|
24289
26196
|
// src/webhook-tools.ts
|
|
24290
|
-
function
|
|
26197
|
+
function mapMcpError17(error) {
|
|
24291
26198
|
if (error instanceof WebhookApiError) {
|
|
24292
26199
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
24293
26200
|
}
|
|
@@ -24308,7 +26215,7 @@ function createWebhookMcpTools(api) {
|
|
|
24308
26215
|
webhooks: await api.listWebhooks(requestInput)
|
|
24309
26216
|
};
|
|
24310
26217
|
} catch (error) {
|
|
24311
|
-
|
|
26218
|
+
mapMcpError17(error);
|
|
24312
26219
|
}
|
|
24313
26220
|
},
|
|
24314
26221
|
async create_webhook(input) {
|
|
@@ -24329,7 +26236,7 @@ function createWebhookMcpTools(api) {
|
|
|
24329
26236
|
webhook: await api.createWebhook(requestInput)
|
|
24330
26237
|
};
|
|
24331
26238
|
} catch (error) {
|
|
24332
|
-
|
|
26239
|
+
mapMcpError17(error);
|
|
24333
26240
|
}
|
|
24334
26241
|
},
|
|
24335
26242
|
async update_webhook(input) {
|
|
@@ -24355,7 +26262,7 @@ function createWebhookMcpTools(api) {
|
|
|
24355
26262
|
webhook: await api.updateWebhook(requestInput)
|
|
24356
26263
|
};
|
|
24357
26264
|
} catch (error) {
|
|
24358
|
-
|
|
26265
|
+
mapMcpError17(error);
|
|
24359
26266
|
}
|
|
24360
26267
|
},
|
|
24361
26268
|
async delete_webhook(input) {
|
|
@@ -24368,7 +26275,7 @@ function createWebhookMcpTools(api) {
|
|
|
24368
26275
|
})
|
|
24369
26276
|
};
|
|
24370
26277
|
} catch (error) {
|
|
24371
|
-
|
|
26278
|
+
mapMcpError17(error);
|
|
24372
26279
|
}
|
|
24373
26280
|
},
|
|
24374
26281
|
async test_webhook(input) {
|
|
@@ -24385,7 +26292,7 @@ function createWebhookMcpTools(api) {
|
|
|
24385
26292
|
delivery: await api.testWebhook(requestInput)
|
|
24386
26293
|
};
|
|
24387
26294
|
} catch (error) {
|
|
24388
|
-
|
|
26295
|
+
mapMcpError17(error);
|
|
24389
26296
|
}
|
|
24390
26297
|
},
|
|
24391
26298
|
async list_webhook_deliveries(input) {
|
|
@@ -24402,7 +26309,7 @@ function createWebhookMcpTools(api) {
|
|
|
24402
26309
|
deliveries: await api.listWebhookDeliveries(requestInput)
|
|
24403
26310
|
};
|
|
24404
26311
|
} catch (error) {
|
|
24405
|
-
|
|
26312
|
+
mapMcpError17(error);
|
|
24406
26313
|
}
|
|
24407
26314
|
},
|
|
24408
26315
|
async retry_webhook_delivery(input) {
|
|
@@ -24414,14 +26321,14 @@ function createWebhookMcpTools(api) {
|
|
|
24414
26321
|
deliveryId: String(input["deliveryId"])
|
|
24415
26322
|
});
|
|
24416
26323
|
} catch (error) {
|
|
24417
|
-
|
|
26324
|
+
mapMcpError17(error);
|
|
24418
26325
|
}
|
|
24419
26326
|
}
|
|
24420
26327
|
};
|
|
24421
26328
|
}
|
|
24422
26329
|
|
|
24423
26330
|
// src/weekly-report-tools.ts
|
|
24424
|
-
function
|
|
26331
|
+
function mapMcpError18(error) {
|
|
24425
26332
|
if (error instanceof WeeklyReportApiError) {
|
|
24426
26333
|
throw new Error(`mcp_tool_error:${error.code}`);
|
|
24427
26334
|
}
|
|
@@ -24439,7 +26346,7 @@ function createWeeklyReportMcpTools(api) {
|
|
|
24439
26346
|
})
|
|
24440
26347
|
};
|
|
24441
26348
|
} catch (error) {
|
|
24442
|
-
|
|
26349
|
+
mapMcpError18(error);
|
|
24443
26350
|
}
|
|
24444
26351
|
},
|
|
24445
26352
|
async create_weekly_report_channel(input) {
|
|
@@ -24455,7 +26362,7 @@ function createWeeklyReportMcpTools(api) {
|
|
|
24455
26362
|
})
|
|
24456
26363
|
};
|
|
24457
26364
|
} catch (error) {
|
|
24458
|
-
|
|
26365
|
+
mapMcpError18(error);
|
|
24459
26366
|
}
|
|
24460
26367
|
},
|
|
24461
26368
|
async update_weekly_report_channel(input) {
|
|
@@ -24470,7 +26377,7 @@ function createWeeklyReportMcpTools(api) {
|
|
|
24470
26377
|
})
|
|
24471
26378
|
};
|
|
24472
26379
|
} catch (error) {
|
|
24473
|
-
|
|
26380
|
+
mapMcpError18(error);
|
|
24474
26381
|
}
|
|
24475
26382
|
},
|
|
24476
26383
|
async delete_weekly_report_channel(input) {
|
|
@@ -24482,7 +26389,7 @@ function createWeeklyReportMcpTools(api) {
|
|
|
24482
26389
|
})
|
|
24483
26390
|
};
|
|
24484
26391
|
} catch (error) {
|
|
24485
|
-
|
|
26392
|
+
mapMcpError18(error);
|
|
24486
26393
|
}
|
|
24487
26394
|
}
|
|
24488
26395
|
};
|
|
@@ -24538,6 +26445,7 @@ async function createDefaultMcpTools(input = {}) {
|
|
|
24538
26445
|
...createWeeklyReportMcpTools(createWeeklyReportApi(httpClient)),
|
|
24539
26446
|
...createAlertMcpTools(createAlertApi(httpClient)),
|
|
24540
26447
|
...createProjectMcpTools(createProjectManagementApi(httpClient)),
|
|
26448
|
+
...createCaptureRuleMcpTools(createCaptureRuleApi(httpClient)),
|
|
24541
26449
|
...createCapturePolicyMcpTools(createCapturePolicyApi(httpClient)),
|
|
24542
26450
|
...createImprovementSettingsMcpTools(createImprovementSettingsApi(httpClient)),
|
|
24543
26451
|
...createProbeMcpTools(createProbeApi(httpClient)),
|
|
@@ -26461,6 +28369,65 @@ var MCP_TOOL_CATALOG = [
|
|
|
26461
28369
|
projectId: external_exports.string()
|
|
26462
28370
|
})
|
|
26463
28371
|
},
|
|
28372
|
+
{
|
|
28373
|
+
name: "list_capture_rules",
|
|
28374
|
+
group: "capture_rules",
|
|
28375
|
+
description: "List project capture rules.",
|
|
28376
|
+
inputSchema: external_exports.object({
|
|
28377
|
+
bearerToken: external_exports.string(),
|
|
28378
|
+
projectId: external_exports.string()
|
|
28379
|
+
})
|
|
28380
|
+
},
|
|
28381
|
+
{
|
|
28382
|
+
name: "create_capture_rule",
|
|
28383
|
+
group: "capture_rules",
|
|
28384
|
+
description: "Create a project capture rule.",
|
|
28385
|
+
inputSchema: external_exports.object({
|
|
28386
|
+
bearerToken: external_exports.string(),
|
|
28387
|
+
projectId: external_exports.string(),
|
|
28388
|
+
create: jsonObjectSchema
|
|
28389
|
+
})
|
|
28390
|
+
},
|
|
28391
|
+
{
|
|
28392
|
+
name: "update_capture_rule",
|
|
28393
|
+
group: "capture_rules",
|
|
28394
|
+
description: "Update a project capture rule.",
|
|
28395
|
+
inputSchema: external_exports.object({
|
|
28396
|
+
bearerToken: external_exports.string(),
|
|
28397
|
+
projectId: external_exports.string(),
|
|
28398
|
+
ruleId: external_exports.string(),
|
|
28399
|
+
update: jsonObjectSchema
|
|
28400
|
+
})
|
|
28401
|
+
},
|
|
28402
|
+
{
|
|
28403
|
+
name: "delete_capture_rule",
|
|
28404
|
+
group: "capture_rules",
|
|
28405
|
+
description: "Delete a project capture rule.",
|
|
28406
|
+
inputSchema: external_exports.object({
|
|
28407
|
+
bearerToken: external_exports.string(),
|
|
28408
|
+
projectId: external_exports.string(),
|
|
28409
|
+
ruleId: external_exports.string()
|
|
28410
|
+
})
|
|
28411
|
+
},
|
|
28412
|
+
{
|
|
28413
|
+
name: "suggest_capture_rules_from_incident",
|
|
28414
|
+
group: "capture_rules",
|
|
28415
|
+
description: "Generate deterministic capture rule suggestions from an incident bundle.",
|
|
28416
|
+
inputSchema: external_exports.object({
|
|
28417
|
+
bearerToken: external_exports.string(),
|
|
28418
|
+
incidentId: external_exports.string()
|
|
28419
|
+
})
|
|
28420
|
+
},
|
|
28421
|
+
{
|
|
28422
|
+
name: "create_capture_rule_from_incident_suggestion",
|
|
28423
|
+
group: "capture_rules",
|
|
28424
|
+
description: "Create a capture rule from an incident-derived suggestion.",
|
|
28425
|
+
inputSchema: external_exports.object({
|
|
28426
|
+
bearerToken: external_exports.string(),
|
|
28427
|
+
incidentId: external_exports.string(),
|
|
28428
|
+
create: jsonObjectSchema
|
|
28429
|
+
})
|
|
28430
|
+
},
|
|
26464
28431
|
{
|
|
26465
28432
|
name: "get_capture_policy",
|
|
26466
28433
|
group: "capture_policy",
|