@debugbundle/cli 1.2.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.cjs +541 -18
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -14771,7 +14771,7 @@ function isIpLikeHost(value) {
|
|
|
14771
14771
|
return /^(?:\d{1,3}\.){3}\d{1,3}$/.test(host) || /^\[[0-9a-f:]+\]$/i.test(host) || host.includes(":") && /^[0-9a-f:]+$/i.test(host);
|
|
14772
14772
|
}
|
|
14773
14773
|
|
|
14774
|
-
// ../../packages/shared-types/src/capture-
|
|
14774
|
+
// ../../packages/shared-types/src/capture-rule-schemas.ts
|
|
14775
14775
|
var CAPTURE_RULE_EVENT_TYPES = [
|
|
14776
14776
|
"backend_exception",
|
|
14777
14777
|
"request_event",
|
|
@@ -14799,6 +14799,7 @@ var CaptureRuleSampleEventClassSchema = external_exports.enum(CaptureRuleSampleE
|
|
|
14799
14799
|
var CaptureRuleRuntimeSchema = external_exports.enum(CAPTURE_RULE_RUNTIME_VALUES);
|
|
14800
14800
|
var CaptureRuleEventTypeSchema = external_exports.enum(CAPTURE_RULE_EVENT_TYPES);
|
|
14801
14801
|
var BrowserEventKindSchema = external_exports.enum(["window_error", "resource_error"]);
|
|
14802
|
+
var CaptureRuleClientKindSchema = external_exports.enum(["human", "bot", "unknown"]);
|
|
14802
14803
|
function normalizeOptionalTrimmedString(value) {
|
|
14803
14804
|
const trimmed = value?.trim();
|
|
14804
14805
|
return trimmed && trimmed.length > 0 ? trimmed : void 0;
|
|
@@ -14876,6 +14877,9 @@ var CaptureRuleMatcherSchema = external_exports.object({
|
|
|
14876
14877
|
message_contains: external_exports.string().min(1).max(500).optional(),
|
|
14877
14878
|
message_equals: external_exports.string().min(1).max(500).optional(),
|
|
14878
14879
|
browser_event_kind: BrowserEventKindSchema.optional(),
|
|
14880
|
+
browser_event_opaque: external_exports.boolean().optional(),
|
|
14881
|
+
client_kind: CaptureRuleClientKindSchema.optional(),
|
|
14882
|
+
bot_family: external_exports.string().min(1).max(120).optional(),
|
|
14879
14883
|
resource_url: UrlMatcherSchema.optional(),
|
|
14880
14884
|
request_url: UrlMatcherSchema.optional(),
|
|
14881
14885
|
status_codes: external_exports.array(external_exports.number().int().min(100).max(599)).min(1).optional(),
|
|
@@ -14890,6 +14894,7 @@ var CaptureRuleMatcherSchema = external_exports.object({
|
|
|
14890
14894
|
const errorName = normalizeOptionalTrimmedString(value.error_name);
|
|
14891
14895
|
const messageContains = normalizeOptionalTrimmedString(value.message_contains);
|
|
14892
14896
|
const messageEquals = normalizeOptionalTrimmedString(value.message_equals);
|
|
14897
|
+
const botFamily = normalizeOptionalTrimmedString(value.bot_family);
|
|
14893
14898
|
const statusCodes = normalizeNumberArray(value.status_codes);
|
|
14894
14899
|
if (eventTypes !== void 0) {
|
|
14895
14900
|
normalized.event_types = eventTypes;
|
|
@@ -14918,6 +14923,15 @@ var CaptureRuleMatcherSchema = external_exports.object({
|
|
|
14918
14923
|
if (value.browser_event_kind !== void 0) {
|
|
14919
14924
|
normalized.browser_event_kind = value.browser_event_kind;
|
|
14920
14925
|
}
|
|
14926
|
+
if (value.browser_event_opaque !== void 0) {
|
|
14927
|
+
normalized.browser_event_opaque = value.browser_event_opaque;
|
|
14928
|
+
}
|
|
14929
|
+
if (value.client_kind !== void 0) {
|
|
14930
|
+
normalized.client_kind = value.client_kind;
|
|
14931
|
+
}
|
|
14932
|
+
if (botFamily !== void 0) {
|
|
14933
|
+
normalized.bot_family = botFamily;
|
|
14934
|
+
}
|
|
14921
14935
|
if (value.resource_url !== void 0) {
|
|
14922
14936
|
normalized.resource_url = value.resource_url;
|
|
14923
14937
|
}
|
|
@@ -14944,6 +14958,9 @@ var CaptureRuleMatcherSchema = external_exports.object({
|
|
|
14944
14958
|
"message_contains",
|
|
14945
14959
|
"message_equals",
|
|
14946
14960
|
"browser_event_kind",
|
|
14961
|
+
"browser_event_opaque",
|
|
14962
|
+
"client_kind",
|
|
14963
|
+
"bot_family",
|
|
14947
14964
|
"resource_url",
|
|
14948
14965
|
"request_url",
|
|
14949
14966
|
"status_codes",
|
|
@@ -15126,6 +15143,8 @@ var CaptureRulesFileSchema = external_exports.object({
|
|
|
15126
15143
|
version: external_exports.literal(1),
|
|
15127
15144
|
rules: external_exports.array(CaptureRuleSchema)
|
|
15128
15145
|
});
|
|
15146
|
+
|
|
15147
|
+
// ../../packages/shared-types/src/capture-rule-evaluation.ts
|
|
15129
15148
|
var CaptureRuleEvaluationUrlSchema = external_exports.object({
|
|
15130
15149
|
host: external_exports.string().min(1).transform((value) => value.toLowerCase()).optional(),
|
|
15131
15150
|
path: external_exports.string().min(1).transform((value) => value.startsWith("/") ? value : `/${value}`)
|
|
@@ -15141,11 +15160,40 @@ var CaptureRuleEvaluationContextSchema = external_exports.object({
|
|
|
15141
15160
|
error_name: external_exports.string().min(1).optional(),
|
|
15142
15161
|
message: external_exports.string().min(1).optional(),
|
|
15143
15162
|
browser_event_kind: BrowserEventKindSchema.optional(),
|
|
15163
|
+
browser_event_opaque: external_exports.boolean().optional(),
|
|
15164
|
+
client_kind: CaptureRuleClientKindSchema.optional(),
|
|
15165
|
+
bot_family: external_exports.string().min(1).max(120).optional(),
|
|
15144
15166
|
resource_url: CaptureRuleEvaluationUrlSchema.optional(),
|
|
15145
15167
|
request_url: CaptureRuleEvaluationUrlSchema.optional(),
|
|
15146
15168
|
status_code: external_exports.number().int().min(0).max(599).optional(),
|
|
15147
15169
|
fingerprint: CaptureRuleFingerprintSchema.optional()
|
|
15148
15170
|
});
|
|
15171
|
+
function classifyCaptureRuleClientFromUserAgent(userAgent) {
|
|
15172
|
+
if (userAgent === null || userAgent === void 0) {
|
|
15173
|
+
return { client_kind: "unknown" };
|
|
15174
|
+
}
|
|
15175
|
+
const lower = userAgent.toLowerCase();
|
|
15176
|
+
const knownBots = [
|
|
15177
|
+
{ family: "Googlebot", markers: ["googlebot", "adsbot-google", "google-inspectiontool"] },
|
|
15178
|
+
{ family: "Bingbot", markers: ["bingbot", "msnbot"] },
|
|
15179
|
+
{ family: "DuckDuckBot", markers: ["duckduckbot"] },
|
|
15180
|
+
{ family: "Applebot", markers: ["applebot"] },
|
|
15181
|
+
{ family: "YandexBot", markers: ["yandexbot"] },
|
|
15182
|
+
{ family: "Baiduspider", markers: ["baiduspider"] },
|
|
15183
|
+
{ family: "FacebookBot", markers: ["facebookexternalhit", "facebot"] },
|
|
15184
|
+
{ family: "LinkedInBot", markers: ["linkedinbot"] },
|
|
15185
|
+
{ family: "TwitterBot", markers: ["twitterbot"] },
|
|
15186
|
+
{ family: "Slackbot", markers: ["slackbot"] }
|
|
15187
|
+
];
|
|
15188
|
+
const knownBot = knownBots.find((entry) => entry.markers.some((marker) => lower.includes(marker)));
|
|
15189
|
+
if (knownBot !== void 0) {
|
|
15190
|
+
return { client_kind: "bot", bot_family: knownBot.family };
|
|
15191
|
+
}
|
|
15192
|
+
if (["bot", "crawler", "spider", "slurp"].some((marker) => lower.includes(marker))) {
|
|
15193
|
+
return { client_kind: "bot", bot_family: "OtherBot" };
|
|
15194
|
+
}
|
|
15195
|
+
return { client_kind: "human" };
|
|
15196
|
+
}
|
|
15149
15197
|
|
|
15150
15198
|
// ../../packages/shared-types/src/capture-rule-suggestions.ts
|
|
15151
15199
|
var CaptureRuleSuggestionConfidenceSchema = external_exports.enum(["high", "medium", "low"]);
|
|
@@ -15355,6 +15403,12 @@ var BrowserExceptionEventSchema = external_exports.object({
|
|
|
15355
15403
|
}).strict().optional(),
|
|
15356
15404
|
opaque: external_exports.boolean()
|
|
15357
15405
|
}).strict();
|
|
15406
|
+
var FrontendRejectionReasonSchema = external_exports.object({
|
|
15407
|
+
kind: external_exports.enum(["error", "string", "object", "null", "undefined", "unknown"]),
|
|
15408
|
+
name: external_exports.string().min(1).optional(),
|
|
15409
|
+
message: external_exports.string().min(1).optional(),
|
|
15410
|
+
preview: external_exports.string().min(1).optional()
|
|
15411
|
+
}).strict();
|
|
15358
15412
|
var FrontendExceptionPayloadSchema = external_exports.object({
|
|
15359
15413
|
name: external_exports.string().min(1),
|
|
15360
15414
|
message: external_exports.string().min(1),
|
|
@@ -15367,6 +15421,7 @@ var FrontendExceptionPayloadSchema = external_exports.object({
|
|
|
15367
15421
|
breadcrumbs: external_exports.array(FrontendExceptionBreadcrumbSchema).optional(),
|
|
15368
15422
|
device: DeviceInfoSchema.nullable().optional(),
|
|
15369
15423
|
browser_event: BrowserExceptionEventSchema.optional(),
|
|
15424
|
+
rejection_reason: FrontendRejectionReasonSchema.optional(),
|
|
15370
15425
|
dom_context: external_exports.object({
|
|
15371
15426
|
mode: external_exports.literal("lightweight"),
|
|
15372
15427
|
html_excerpt: external_exports.string().min(1)
|
|
@@ -15818,7 +15873,7 @@ function buildSkill() {
|
|
|
15818
15873
|
"2. Inspect the incident bundle and reproduction artifact before proposing a fix.",
|
|
15819
15874
|
"3. Run `debugbundle analyze --type improvement --local` after local processing when you need a deterministic change plan.",
|
|
15820
15875
|
"4. Apply the narrowest fix, then validate it with the repository test workflow from `.debugbundle/profile.json`.",
|
|
15821
|
-
"5. When the fix is confirmed, or when the incident was intentionally generated for smoke, verification, or dogfooding, resolve it with `debugbundle resolve <incident-id
|
|
15876
|
+
"5. When the fix is confirmed, or when the incident was intentionally generated for smoke, verification, or dogfooding, resolve it with `debugbundle resolve <incident-id> [incident-id ...]` or MCP `resolve_incident` / `resolve_incidents` so the open queue stays actionable.",
|
|
15822
15877
|
"",
|
|
15823
15878
|
"## Incident Hygiene",
|
|
15824
15879
|
"",
|
|
@@ -15827,6 +15882,15 @@ function buildSkill() {
|
|
|
15827
15882
|
"- Reopen or leave open if the failure is still present, the validation is incomplete, or the incident represents a live unresolved problem.",
|
|
15828
15883
|
"- If a resolved incident regresses, let the platform move it back to `regressed` through normal incident lifecycle behavior.",
|
|
15829
15884
|
"",
|
|
15885
|
+
"## Noise Management",
|
|
15886
|
+
"",
|
|
15887
|
+
"When incident evidence shows repeated low-value operational noise rather than a product bug, evaluate whether a scoped capture rule or capture-policy path rule should handle future matches.",
|
|
15888
|
+
"",
|
|
15889
|
+
"- Run `debugbundle capture-rule suggest <incident-id> --json` before creating a manual rule. Apply deterministic suggestions with `debugbundle capture-rule create-from-suggestion <incident-id> --suggestion-id <id>` after confirming the scope is safe.",
|
|
15890
|
+
"- Prefer project capture rules for operational noise because they are centralized, auditable, and enforced by ingestion and processing. Use SDK `beforeSend` only for app-owned local policy such as final redaction or events that must never leave the runtime.",
|
|
15891
|
+
"- Scope frontend noise by structured evidence such as service, environment, `browser_event_kind`, `browser_event_opaque`, `client_kind`, `bot_family`, and message fields. Do not broadly demote generic `Unhandled promise rejection` incidents without bot-scoped or otherwise narrow evidence.",
|
|
15892
|
+
"- For expected or intentionally promoted 4xx responses on known routes, use capture-policy client-error path rules instead of promoting all client errors: `debugbundle capture-policy set --client-error-path-rule <status=/path/*@GET>`.",
|
|
15893
|
+
"",
|
|
15830
15894
|
"## Profile Validation",
|
|
15831
15895
|
"",
|
|
15832
15896
|
"Use this task after setup or whenever architecture changes make the static profile stale.",
|
|
@@ -15889,10 +15953,21 @@ function buildCliReference() {
|
|
|
15889
15953
|
"- `debugbundle explain <incident-id> [--source <local|cloud>] [--json]`",
|
|
15890
15954
|
"- `debugbundle bundle <incident-id> [--source <local|cloud>] [--json]`",
|
|
15891
15955
|
"- `debugbundle reproduce <incident-id> [--source <local|cloud>] [--json]`",
|
|
15892
|
-
"- `debugbundle resolve <incident-id> [--source <local|cloud>] [--json]`",
|
|
15893
|
-
"- `debugbundle reopen <incident-id> [--source <local|cloud>] [--json]`",
|
|
15956
|
+
"- `debugbundle resolve <incident-id> [incident-id ...] [--source <local|cloud>] [--json]`",
|
|
15957
|
+
"- `debugbundle reopen <incident-id> [incident-id ...] [--source <local|cloud>] [--json]`",
|
|
15894
15958
|
"- `debugbundle analyze --type improvement --local`",
|
|
15895
15959
|
"",
|
|
15960
|
+
"## Noise Management",
|
|
15961
|
+
"",
|
|
15962
|
+
"- `debugbundle capture-rule suggest <incident-id> [--auth-file <path>] [--json]`",
|
|
15963
|
+
"- `debugbundle capture-rule create-from-suggestion <incident-id> --suggestion-id <id> [--name <name>] [--expires-at <ISO8601>] [--auth-file <path>] [--json]`",
|
|
15964
|
+
"- `debugbundle capture-rule list --project-id <id> [--auth-file <path>] [--json]`",
|
|
15965
|
+
"- `debugbundle capture-rule create --project-id <id> --name <name> --action <demote|sample|drop> --matcher-json <json> [--auth-file <path>] [--json]`",
|
|
15966
|
+
"- `debugbundle capture-policy get [--project <id>] [--json]`",
|
|
15967
|
+
"- `debugbundle capture-policy set [--project <id>] --client-error-path-rule <404=/path/*@GET,POST> [--json]`",
|
|
15968
|
+
"",
|
|
15969
|
+
"Use capture-rule suggestions for repeated operational noise after inspecting an incident bundle. Use capture-policy client-error path rules for route-scoped 4xx incidents instead of promoting all client errors.",
|
|
15970
|
+
"",
|
|
15896
15971
|
"## Operational Paths",
|
|
15897
15972
|
"",
|
|
15898
15973
|
"- `.debugbundle/profile.json` \u2014 committed project map and agent validation state",
|
|
@@ -15923,7 +15998,7 @@ function buildCliReference() {
|
|
|
15923
15998
|
"```bash",
|
|
15924
15999
|
"debugbundle incidents --status open --json \\",
|
|
15925
16000
|
` | jq -r '.incidents[] | select(.title | test("smoke test|dogfood|verification|synthetic"; "i")) | .incident_id' \\`,
|
|
15926
|
-
" | xargs
|
|
16001
|
+
" | xargs debugbundle resolve",
|
|
15927
16002
|
"```",
|
|
15928
16003
|
""
|
|
15929
16004
|
].join("\n");
|
|
@@ -15942,19 +16017,28 @@ function buildMcpReference() {
|
|
|
15942
16017
|
"- `get_incident_context` \u2014 fetch deterministic explanation context for triage.",
|
|
15943
16018
|
"- `get_bundle` \u2014 fetch the full debug bundle before proposing a fix.",
|
|
15944
16019
|
"- `get_reproduction` \u2014 fetch reproduction guidance before editing code.",
|
|
15945
|
-
"- `resolve_incident` / `reopen_incident` \u2014 update lifecycle state after validation.",
|
|
16020
|
+
"- `resolve_incident` / `resolve_incidents` / `reopen_incident` / `reopen_incidents` \u2014 update lifecycle state after validation.",
|
|
15946
16021
|
"- `analyze` \u2014 run local agent-oriented analysis from local bundles and skill schemas.",
|
|
15947
16022
|
"",
|
|
15948
16023
|
"- Prefer bundle retrieval tools before reading raw repository files.",
|
|
15949
16024
|
"- Use MCP bundle access when the current issue originated in production.",
|
|
15950
|
-
"- Resolve fixed or intentionally generated incidents with `resolve_incident` so open incidents stay actionable.",
|
|
16025
|
+
"- Resolve fixed or intentionally generated incidents with `resolve_incident` or `resolve_incidents` so open incidents stay actionable.",
|
|
15951
16026
|
"- Fall back to local CLI processing when the project is local-only.",
|
|
15952
16027
|
"",
|
|
16028
|
+
"## Noise and Capture Policy Tools",
|
|
16029
|
+
"",
|
|
16030
|
+
"- `suggest_capture_rules_from_incident` \u2014 generate deterministic capture-rule suggestions from an incident bundle.",
|
|
16031
|
+
"- `create_capture_rule_from_incident_suggestion` \u2014 apply a confirmed suggestion.",
|
|
16032
|
+
"- `list_capture_rules`, `create_capture_rule`, `update_capture_rule`, `delete_capture_rule` \u2014 manage project capture rules.",
|
|
16033
|
+
"- `get_capture_policy`, `update_capture_policy` \u2014 review or update capture policy, including path-scoped client-error incident rules.",
|
|
16034
|
+
"",
|
|
16035
|
+
"Use these tools for repeated low-value operational noise only after inspecting incident evidence. Keep frontend suppression scoped by structured browser and client signals, and use path-scoped capture policy for known 4xx routes.",
|
|
16036
|
+
"",
|
|
15953
16037
|
"## Smoke-Test Cleanup Recipe",
|
|
15954
16038
|
"",
|
|
15955
16039
|
'1. Call `list_incidents` with `status: "open"`.',
|
|
15956
16040
|
"2. Filter incidents whose titles show they were intentionally generated for smoke, dogfood, verification, or synthetic checks.",
|
|
15957
|
-
"3. Call `
|
|
16041
|
+
"3. Call `resolve_incidents` for verified synthetic incidents, or `resolve_incident` for a single incident.",
|
|
15958
16042
|
"4. Call `list_incidents` again and confirm the open queue only contains actionable failures.",
|
|
15959
16043
|
""
|
|
15960
16044
|
].join("\n");
|
|
@@ -16074,6 +16158,16 @@ function buildSkillEvals() {
|
|
|
16074
16158
|
"Leave unresolved incidents open when the failure is still live or unverified."
|
|
16075
16159
|
]
|
|
16076
16160
|
},
|
|
16161
|
+
{
|
|
16162
|
+
name: "noise_management_guidance",
|
|
16163
|
+
prompt: "The same low-value frontend incident keeps reopening. Confirm the skill tells the agent how to evaluate operational noise without hiding real bugs.",
|
|
16164
|
+
expected_behavior: [
|
|
16165
|
+
"Inspect incident evidence before creating a rule.",
|
|
16166
|
+
"Use capture-rule suggestions for repeated operational noise.",
|
|
16167
|
+
"Keep generic frontend suppression narrow with structured browser or bot signals.",
|
|
16168
|
+
"Use capture-policy path rules for known route-scoped 4xx incidents."
|
|
16169
|
+
]
|
|
16170
|
+
},
|
|
16077
16171
|
{
|
|
16078
16172
|
name: "artifact_path_discovery",
|
|
16079
16173
|
prompt: "The user reports an unknown local runtime error. Confirm the skill tells the agent which DebugBundle paths and commands to inspect first.",
|
|
@@ -16736,6 +16830,9 @@ function createRetrievalApi(client) {
|
|
|
16736
16830
|
if (input2.severity !== void 0) {
|
|
16737
16831
|
query.set("severity", input2.severity);
|
|
16738
16832
|
}
|
|
16833
|
+
if (input2.firstSeenAfter !== void 0) {
|
|
16834
|
+
query.set("first_seen_after", input2.firstSeenAfter);
|
|
16835
|
+
}
|
|
16739
16836
|
if (input2.cursor !== void 0) {
|
|
16740
16837
|
query.set("cursor", input2.cursor);
|
|
16741
16838
|
}
|
|
@@ -16992,6 +17089,88 @@ function createRetrievalApi(client) {
|
|
|
16992
17089
|
};
|
|
16993
17090
|
}
|
|
16994
17091
|
|
|
17092
|
+
// ../../packages/storage/src/account-analytics-store.ts
|
|
17093
|
+
var ACCOUNT_METRIC_KEYS = [
|
|
17094
|
+
"account_created",
|
|
17095
|
+
"account_deleted",
|
|
17096
|
+
"project_created",
|
|
17097
|
+
"project_deleted",
|
|
17098
|
+
"raw_events_accepted",
|
|
17099
|
+
"raw_events_rejected",
|
|
17100
|
+
"events_rejected_malformed",
|
|
17101
|
+
"events_rejected_rate_limited",
|
|
17102
|
+
"events_rejected_quota",
|
|
17103
|
+
"events_rejected_capture_policy",
|
|
17104
|
+
"events_rejected_capture_rule",
|
|
17105
|
+
"billable_events_counted",
|
|
17106
|
+
"incident_signal_events_counted",
|
|
17107
|
+
"context_signal_events_counted",
|
|
17108
|
+
"operational_signal_events_counted",
|
|
17109
|
+
"local_verification_events_accepted",
|
|
17110
|
+
"cloud_verification_events_accepted",
|
|
17111
|
+
"incidents_opened",
|
|
17112
|
+
"incidents_resolved",
|
|
17113
|
+
"incidents_reopened",
|
|
17114
|
+
"incidents_regressed",
|
|
17115
|
+
"incident_occurrences",
|
|
17116
|
+
"incident_occurrences_high_severity",
|
|
17117
|
+
"incident_occurrences_critical_severity",
|
|
17118
|
+
"incidents_auto_detected_spiking",
|
|
17119
|
+
"failure_bundles_created",
|
|
17120
|
+
"failure_bundles_updated",
|
|
17121
|
+
"failure_bundle_generations_failed",
|
|
17122
|
+
"improvement_bundles_created",
|
|
17123
|
+
"improvement_bundles_updated",
|
|
17124
|
+
"improvement_bundle_generations_failed",
|
|
17125
|
+
"reproductions_created",
|
|
17126
|
+
"reproductions_failed",
|
|
17127
|
+
"retention_bundle_owners_rotated",
|
|
17128
|
+
"improvements_opened",
|
|
17129
|
+
"improvements_resolved",
|
|
17130
|
+
"improvements_reopened",
|
|
17131
|
+
"improvements_snoozed",
|
|
17132
|
+
"recurring_incident_improvements_opened",
|
|
17133
|
+
"post_deploy_regression_improvements_opened",
|
|
17134
|
+
"slow_request_improvements_opened",
|
|
17135
|
+
"request_failure_improvements_opened",
|
|
17136
|
+
"warning_log_improvements_opened",
|
|
17137
|
+
"alert_deliveries_created",
|
|
17138
|
+
"alert_deliveries_delivered",
|
|
17139
|
+
"alert_deliveries_failed",
|
|
17140
|
+
"alert_email_digests_sent",
|
|
17141
|
+
"operational_emails_sent",
|
|
17142
|
+
"weekly_reports_sent",
|
|
17143
|
+
"weekly_reports_failed",
|
|
17144
|
+
"webhook_deliveries_created",
|
|
17145
|
+
"webhook_deliveries_delivered",
|
|
17146
|
+
"webhook_deliveries_failed",
|
|
17147
|
+
"webhooks_auto_disabled",
|
|
17148
|
+
"github_dispatches_created",
|
|
17149
|
+
"github_dispatches_delivered",
|
|
17150
|
+
"github_dispatches_failed",
|
|
17151
|
+
"github_dispatch_rules_created",
|
|
17152
|
+
"github_dispatch_rules_deleted",
|
|
17153
|
+
"remote_probe_activations_created",
|
|
17154
|
+
"remote_probe_activations_expired",
|
|
17155
|
+
"probe_events_accepted",
|
|
17156
|
+
"capture_rules_created",
|
|
17157
|
+
"capture_rules_deleted",
|
|
17158
|
+
"capture_policy_updates",
|
|
17159
|
+
"trial_started",
|
|
17160
|
+
"trial_converted",
|
|
17161
|
+
"trial_expired",
|
|
17162
|
+
"plan_upgraded",
|
|
17163
|
+
"plan_downgraded",
|
|
17164
|
+
"capacity_units_purchased",
|
|
17165
|
+
"capacity_units_reduced",
|
|
17166
|
+
"allowance_warning_emails_sent",
|
|
17167
|
+
"allowance_limit_emails_sent",
|
|
17168
|
+
"projects_existing_at_account_deletion",
|
|
17169
|
+
"open_incidents_existing_at_account_deletion",
|
|
17170
|
+
"open_improvements_existing_at_account_deletion"
|
|
17171
|
+
];
|
|
17172
|
+
var AccountMetricKeySchema = external_exports.enum(ACCOUNT_METRIC_KEYS);
|
|
17173
|
+
|
|
16995
17174
|
// ../../packages/storage/src/incident-context.ts
|
|
16996
17175
|
function isRecord2(value) {
|
|
16997
17176
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -17088,6 +17267,33 @@ function buildRedactionRecord(bundleBody) {
|
|
|
17088
17267
|
notes: readString(redaction["notes"])
|
|
17089
17268
|
};
|
|
17090
17269
|
}
|
|
17270
|
+
function buildBrowserSignalRecord(bundleBody) {
|
|
17271
|
+
const bundle = isRecord2(bundleBody) ? bundleBody : {};
|
|
17272
|
+
const context = isRecord2(bundle["context"]) ? bundle["context"] : {};
|
|
17273
|
+
const frontend = isRecord2(context["frontend"]) ? context["frontend"] : {};
|
|
17274
|
+
const exceptions = Array.isArray(frontend["exceptions"]) ? frontend["exceptions"] : [];
|
|
17275
|
+
let exception;
|
|
17276
|
+
for (let index = exceptions.length - 1; index >= 0; index -= 1) {
|
|
17277
|
+
const candidate = exceptions[index];
|
|
17278
|
+
if (isRecord2(candidate) && isRecord2(candidate["browser_event"])) {
|
|
17279
|
+
exception = candidate;
|
|
17280
|
+
break;
|
|
17281
|
+
}
|
|
17282
|
+
}
|
|
17283
|
+
const browserEvent = isRecord2(exception) && isRecord2(exception["browser_event"]) ? exception["browser_event"] : null;
|
|
17284
|
+
const device = isRecord2(context["device"]) ? context["device"] : {};
|
|
17285
|
+
const client = classifyCaptureRuleClientFromUserAgent(readString(device["user_agent"]) ?? void 0);
|
|
17286
|
+
if (browserEvent === null && client.client_kind === "unknown") {
|
|
17287
|
+
return null;
|
|
17288
|
+
}
|
|
17289
|
+
return {
|
|
17290
|
+
browser_event_kind: readString(browserEvent?.["kind"]),
|
|
17291
|
+
browser_event_opaque: readBoolean(browserEvent?.["opaque"]),
|
|
17292
|
+
browser_event_message: readString(browserEvent?.["message"]),
|
|
17293
|
+
client_kind: client.client_kind,
|
|
17294
|
+
bot_family: client.bot_family ?? null
|
|
17295
|
+
};
|
|
17296
|
+
}
|
|
17091
17297
|
function buildVisibilityRecord(input2) {
|
|
17092
17298
|
const routeTarget = input2.primarySignal.route_template ?? input2.primarySignal.request_path;
|
|
17093
17299
|
const matchedFields = input2.incident.matched_fields.length === 0 ? "none" : input2.incident.matched_fields.join(", ");
|
|
@@ -17125,6 +17331,14 @@ function buildSuggestedNextChecks(input2) {
|
|
|
17125
17331
|
if (input2.deploy.regression_window === true || input2.incident.status === "regressed") {
|
|
17126
17332
|
suggestions.push("Compare this incident against the most recent deploy and recent regressions.");
|
|
17127
17333
|
}
|
|
17334
|
+
if (input2.browserSignal?.browser_event_opaque === true) {
|
|
17335
|
+
suggestions.push("Treat the browser event as opaque; inspect CSP, cross-origin scripts, resource loading, and framework error boundaries before changing application code.");
|
|
17336
|
+
}
|
|
17337
|
+
if (input2.browserSignal?.client_kind === "bot") {
|
|
17338
|
+
suggestions.push(
|
|
17339
|
+
`Review whether ${input2.browserSignal.bot_family ?? "bot"} traffic is operational noise before applying a bot-scoped capture rule.`
|
|
17340
|
+
);
|
|
17341
|
+
}
|
|
17128
17342
|
if (input2.reproduction.status === "pending") {
|
|
17129
17343
|
suggestions.push("Recheck reproduction guidance after the reproduction artifact is ready.");
|
|
17130
17344
|
}
|
|
@@ -17145,6 +17359,7 @@ function buildIncidentContextRecord(input2) {
|
|
|
17145
17359
|
primarySignal
|
|
17146
17360
|
});
|
|
17147
17361
|
const redaction = buildRedactionRecord(bundleBody);
|
|
17362
|
+
const browserSignal = buildBrowserSignalRecord(bundleBody);
|
|
17148
17363
|
return {
|
|
17149
17364
|
incident: input2.incident,
|
|
17150
17365
|
incident_reason: incidentReason,
|
|
@@ -17160,13 +17375,15 @@ function buildIncidentContextRecord(input2) {
|
|
|
17160
17375
|
},
|
|
17161
17376
|
visibility,
|
|
17162
17377
|
redaction,
|
|
17378
|
+
browser_signal: browserSignal,
|
|
17163
17379
|
suggested_next_checks: buildSuggestedNextChecks({
|
|
17164
17380
|
incident: input2.incident,
|
|
17165
17381
|
bundle: input2.bundle,
|
|
17166
17382
|
reproduction: input2.reproduction,
|
|
17167
17383
|
logs,
|
|
17168
17384
|
primarySignal,
|
|
17169
|
-
deploy
|
|
17385
|
+
deploy,
|
|
17386
|
+
browserSignal
|
|
17170
17387
|
})
|
|
17171
17388
|
};
|
|
17172
17389
|
}
|
|
@@ -17239,6 +17456,9 @@ function deriveIncidentReasonFromSourceEventTypes(eventTypes) {
|
|
|
17239
17456
|
// ../../packages/auth/src/primitives.ts
|
|
17240
17457
|
var import_argon2 = require("@node-rs/argon2");
|
|
17241
17458
|
|
|
17459
|
+
// ../../packages/auth/src/account-deletion-auth.ts
|
|
17460
|
+
var DEFAULT_ACCOUNT_DELETION_CODE_LIFETIME_MS = 1e3 * 60 * 10;
|
|
17461
|
+
|
|
17242
17462
|
// ../../packages/auth/src/web-session-auth.ts
|
|
17243
17463
|
var DEFAULT_SESSION_LIFETIME_MS = 1e3 * 60 * 60 * 24 * 7;
|
|
17244
17464
|
var DEFAULT_EMAIL_AUTH_CODE_LIFETIME_MS = 1e3 * 60 * 10;
|
|
@@ -17950,6 +18170,26 @@ var STORAGE_BOOTSTRAP_STATEMENTS = [
|
|
|
17950
18170
|
CREATE INDEX email_auth_challenges_code_hash_idx
|
|
17951
18171
|
ON email_auth_challenges (code_hash)
|
|
17952
18172
|
`,
|
|
18173
|
+
`
|
|
18174
|
+
CREATE TABLE account_deletion_challenges (
|
|
18175
|
+
id uuid PRIMARY KEY,
|
|
18176
|
+
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
18177
|
+
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
18178
|
+
email text NOT NULL,
|
|
18179
|
+
code_hash text NOT NULL,
|
|
18180
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
18181
|
+
expires_at timestamptz NOT NULL,
|
|
18182
|
+
used_at timestamptz
|
|
18183
|
+
)
|
|
18184
|
+
`,
|
|
18185
|
+
`
|
|
18186
|
+
CREATE INDEX account_deletion_challenges_scope_idx
|
|
18187
|
+
ON account_deletion_challenges (organization_id, user_id, lower(email), created_at DESC)
|
|
18188
|
+
`,
|
|
18189
|
+
`
|
|
18190
|
+
CREATE INDEX account_deletion_challenges_code_hash_idx
|
|
18191
|
+
ON account_deletion_challenges (code_hash)
|
|
18192
|
+
`,
|
|
17953
18193
|
`
|
|
17954
18194
|
CREATE TABLE github_device_authorizations (
|
|
17955
18195
|
id uuid PRIMARY KEY,
|
|
@@ -18660,6 +18900,103 @@ var STORAGE_BOOTSTRAP_STATEMENTS = [
|
|
|
18660
18900
|
PRIMARY KEY (organization_id, period_starts_at)
|
|
18661
18901
|
)
|
|
18662
18902
|
`,
|
|
18903
|
+
`
|
|
18904
|
+
CREATE TABLE project_usage_counters (
|
|
18905
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
18906
|
+
period_starts_at timestamptz NOT NULL,
|
|
18907
|
+
raw_ingested_events integer NOT NULL DEFAULT 0,
|
|
18908
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
18909
|
+
PRIMARY KEY (project_id, period_starts_at)
|
|
18910
|
+
)
|
|
18911
|
+
`,
|
|
18912
|
+
`
|
|
18913
|
+
CREATE TABLE account_analytics_accounts (
|
|
18914
|
+
analytics_account_id uuid PRIMARY KEY,
|
|
18915
|
+
organization_id uuid UNIQUE,
|
|
18916
|
+
organization_id_hash text NOT NULL UNIQUE,
|
|
18917
|
+
created_at timestamptz NOT NULL,
|
|
18918
|
+
first_seen_at timestamptz NOT NULL,
|
|
18919
|
+
metrics_collection_started_at timestamptz NOT NULL,
|
|
18920
|
+
backfilled_from_retained_rows_at timestamptz,
|
|
18921
|
+
deleted_at timestamptz,
|
|
18922
|
+
initial_plan text,
|
|
18923
|
+
latest_known_plan text,
|
|
18924
|
+
latest_capacity_units integer,
|
|
18925
|
+
account_deleted boolean NOT NULL DEFAULT false,
|
|
18926
|
+
metrics_schema_version integer NOT NULL DEFAULT 1,
|
|
18927
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
18928
|
+
)
|
|
18929
|
+
`,
|
|
18930
|
+
`
|
|
18931
|
+
CREATE TABLE account_metric_periods (
|
|
18932
|
+
analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
|
|
18933
|
+
period_grain text NOT NULL CHECK (period_grain IN ('day', 'month', 'year', 'lifetime')),
|
|
18934
|
+
period_starts_at timestamptz NOT NULL,
|
|
18935
|
+
metric_key text NOT NULL,
|
|
18936
|
+
metric_value bigint NOT NULL DEFAULT 0,
|
|
18937
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
18938
|
+
PRIMARY KEY (analytics_account_id, period_grain, period_starts_at, metric_key)
|
|
18939
|
+
)
|
|
18940
|
+
`,
|
|
18941
|
+
`
|
|
18942
|
+
CREATE INDEX account_metric_periods_grain_period_metric_idx
|
|
18943
|
+
ON account_metric_periods (period_grain, period_starts_at, metric_key)
|
|
18944
|
+
`,
|
|
18945
|
+
`
|
|
18946
|
+
CREATE INDEX account_metric_periods_account_grain_period_idx
|
|
18947
|
+
ON account_metric_periods (analytics_account_id, period_grain, period_starts_at)
|
|
18948
|
+
`,
|
|
18949
|
+
`
|
|
18950
|
+
CREATE TABLE account_metric_events (
|
|
18951
|
+
dedupe_key_hash text PRIMARY KEY,
|
|
18952
|
+
analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
|
|
18953
|
+
metric_source text NOT NULL,
|
|
18954
|
+
occurred_at timestamptz NOT NULL,
|
|
18955
|
+
recorded_at timestamptz NOT NULL DEFAULT now(),
|
|
18956
|
+
metric_deltas jsonb NOT NULL
|
|
18957
|
+
)
|
|
18958
|
+
`,
|
|
18959
|
+
`
|
|
18960
|
+
CREATE TABLE account_payment_retention_records (
|
|
18961
|
+
id uuid PRIMARY KEY,
|
|
18962
|
+
analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
|
|
18963
|
+
organization_id_hash text NOT NULL,
|
|
18964
|
+
provider text NOT NULL,
|
|
18965
|
+
plan text,
|
|
18966
|
+
billing_state text,
|
|
18967
|
+
stripe_customer_id text,
|
|
18968
|
+
stripe_subscription_id text,
|
|
18969
|
+
billing_period_starts_at timestamptz,
|
|
18970
|
+
billing_period_ends_at timestamptz,
|
|
18971
|
+
additional_capacity_units integer,
|
|
18972
|
+
last_billing_event_id text,
|
|
18973
|
+
account_deleted_at timestamptz NOT NULL,
|
|
18974
|
+
recorded_at timestamptz NOT NULL DEFAULT now(),
|
|
18975
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
18976
|
+
UNIQUE (analytics_account_id, provider)
|
|
18977
|
+
)
|
|
18978
|
+
`,
|
|
18979
|
+
`
|
|
18980
|
+
CREATE INDEX account_payment_retention_records_provider_idx
|
|
18981
|
+
ON account_payment_retention_records (provider, account_deleted_at DESC)
|
|
18982
|
+
`,
|
|
18983
|
+
`
|
|
18984
|
+
CREATE TABLE account_payment_provider_events (
|
|
18985
|
+
provider_event_key text PRIMARY KEY,
|
|
18986
|
+
analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
|
|
18987
|
+
organization_id_hash text NOT NULL,
|
|
18988
|
+
provider text NOT NULL,
|
|
18989
|
+
provider_event_id text NOT NULL,
|
|
18990
|
+
provider_event_type text NOT NULL,
|
|
18991
|
+
processed_at timestamptz NOT NULL,
|
|
18992
|
+
account_deleted_at timestamptz NOT NULL,
|
|
18993
|
+
recorded_at timestamptz NOT NULL DEFAULT now()
|
|
18994
|
+
)
|
|
18995
|
+
`,
|
|
18996
|
+
`
|
|
18997
|
+
CREATE UNIQUE INDEX account_payment_provider_events_provider_event_key
|
|
18998
|
+
ON account_payment_provider_events (provider, provider_event_id)
|
|
18999
|
+
`,
|
|
18663
19000
|
`
|
|
18664
19001
|
CREATE TABLE operational_email_deliveries (
|
|
18665
19002
|
id uuid PRIMARY KEY,
|
|
@@ -19428,6 +19765,141 @@ var STORAGE_SCHEMA_MIGRATIONS = [
|
|
|
19428
19765
|
statements: [
|
|
19429
19766
|
"ALTER TABLE capture_policies ADD COLUMN IF NOT EXISTS immediate_client_error_path_rules jsonb"
|
|
19430
19767
|
]
|
|
19768
|
+
}),
|
|
19769
|
+
defineStorageSchemaMigration({
|
|
19770
|
+
id: "202606100001_add_project_usage_counters",
|
|
19771
|
+
description: "Add durable project-level raw ingestion counters for project dashboard metrics.",
|
|
19772
|
+
statements: [
|
|
19773
|
+
`
|
|
19774
|
+
CREATE TABLE IF NOT EXISTS project_usage_counters (
|
|
19775
|
+
project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
|
19776
|
+
period_starts_at timestamptz NOT NULL,
|
|
19777
|
+
raw_ingested_events integer NOT NULL DEFAULT 0,
|
|
19778
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
19779
|
+
PRIMARY KEY (project_id, period_starts_at)
|
|
19780
|
+
)
|
|
19781
|
+
`
|
|
19782
|
+
]
|
|
19783
|
+
}),
|
|
19784
|
+
defineStorageSchemaMigration({
|
|
19785
|
+
id: "202606100002_add_account_deletion_challenges",
|
|
19786
|
+
description: "Add scoped OTP challenges for account deletion confirmation.",
|
|
19787
|
+
statements: [
|
|
19788
|
+
`
|
|
19789
|
+
CREATE TABLE IF NOT EXISTS account_deletion_challenges (
|
|
19790
|
+
id uuid PRIMARY KEY,
|
|
19791
|
+
organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
19792
|
+
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
19793
|
+
email text NOT NULL,
|
|
19794
|
+
code_hash text NOT NULL,
|
|
19795
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
19796
|
+
expires_at timestamptz NOT NULL,
|
|
19797
|
+
used_at timestamptz
|
|
19798
|
+
)
|
|
19799
|
+
`,
|
|
19800
|
+
`
|
|
19801
|
+
CREATE INDEX IF NOT EXISTS account_deletion_challenges_scope_idx
|
|
19802
|
+
ON account_deletion_challenges (organization_id, user_id, lower(email), created_at DESC)
|
|
19803
|
+
`,
|
|
19804
|
+
`
|
|
19805
|
+
CREATE INDEX IF NOT EXISTS account_deletion_challenges_code_hash_idx
|
|
19806
|
+
ON account_deletion_challenges (code_hash)
|
|
19807
|
+
`
|
|
19808
|
+
]
|
|
19809
|
+
}),
|
|
19810
|
+
defineStorageSchemaMigration({
|
|
19811
|
+
id: "202606100003_add_account_analytics_and_payment_retention",
|
|
19812
|
+
description: "Add deletion-safe account analytics and payment retention ledgers.",
|
|
19813
|
+
statements: [
|
|
19814
|
+
`
|
|
19815
|
+
CREATE TABLE IF NOT EXISTS account_analytics_accounts (
|
|
19816
|
+
analytics_account_id uuid PRIMARY KEY,
|
|
19817
|
+
organization_id uuid UNIQUE,
|
|
19818
|
+
organization_id_hash text NOT NULL UNIQUE,
|
|
19819
|
+
created_at timestamptz NOT NULL,
|
|
19820
|
+
first_seen_at timestamptz NOT NULL,
|
|
19821
|
+
metrics_collection_started_at timestamptz NOT NULL,
|
|
19822
|
+
backfilled_from_retained_rows_at timestamptz,
|
|
19823
|
+
deleted_at timestamptz,
|
|
19824
|
+
initial_plan text,
|
|
19825
|
+
latest_known_plan text,
|
|
19826
|
+
latest_capacity_units integer,
|
|
19827
|
+
account_deleted boolean NOT NULL DEFAULT false,
|
|
19828
|
+
metrics_schema_version integer NOT NULL DEFAULT 1,
|
|
19829
|
+
updated_at timestamptz NOT NULL DEFAULT now()
|
|
19830
|
+
)
|
|
19831
|
+
`,
|
|
19832
|
+
`
|
|
19833
|
+
CREATE TABLE IF NOT EXISTS account_metric_periods (
|
|
19834
|
+
analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
|
|
19835
|
+
period_grain text NOT NULL CHECK (period_grain IN ('day', 'month', 'year', 'lifetime')),
|
|
19836
|
+
period_starts_at timestamptz NOT NULL,
|
|
19837
|
+
metric_key text NOT NULL,
|
|
19838
|
+
metric_value bigint NOT NULL DEFAULT 0,
|
|
19839
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
19840
|
+
PRIMARY KEY (analytics_account_id, period_grain, period_starts_at, metric_key)
|
|
19841
|
+
)
|
|
19842
|
+
`,
|
|
19843
|
+
`
|
|
19844
|
+
CREATE INDEX IF NOT EXISTS account_metric_periods_grain_period_metric_idx
|
|
19845
|
+
ON account_metric_periods (period_grain, period_starts_at, metric_key)
|
|
19846
|
+
`,
|
|
19847
|
+
`
|
|
19848
|
+
CREATE INDEX IF NOT EXISTS account_metric_periods_account_grain_period_idx
|
|
19849
|
+
ON account_metric_periods (analytics_account_id, period_grain, period_starts_at)
|
|
19850
|
+
`,
|
|
19851
|
+
`
|
|
19852
|
+
CREATE TABLE IF NOT EXISTS account_metric_events (
|
|
19853
|
+
dedupe_key_hash text PRIMARY KEY,
|
|
19854
|
+
analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
|
|
19855
|
+
metric_source text NOT NULL,
|
|
19856
|
+
occurred_at timestamptz NOT NULL,
|
|
19857
|
+
recorded_at timestamptz NOT NULL DEFAULT now(),
|
|
19858
|
+
metric_deltas jsonb NOT NULL
|
|
19859
|
+
)
|
|
19860
|
+
`,
|
|
19861
|
+
`
|
|
19862
|
+
CREATE TABLE IF NOT EXISTS account_payment_retention_records (
|
|
19863
|
+
id uuid PRIMARY KEY,
|
|
19864
|
+
analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
|
|
19865
|
+
organization_id_hash text NOT NULL,
|
|
19866
|
+
provider text NOT NULL,
|
|
19867
|
+
plan text,
|
|
19868
|
+
billing_state text,
|
|
19869
|
+
stripe_customer_id text,
|
|
19870
|
+
stripe_subscription_id text,
|
|
19871
|
+
billing_period_starts_at timestamptz,
|
|
19872
|
+
billing_period_ends_at timestamptz,
|
|
19873
|
+
additional_capacity_units integer,
|
|
19874
|
+
last_billing_event_id text,
|
|
19875
|
+
account_deleted_at timestamptz NOT NULL,
|
|
19876
|
+
recorded_at timestamptz NOT NULL DEFAULT now(),
|
|
19877
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
19878
|
+
UNIQUE (analytics_account_id, provider)
|
|
19879
|
+
)
|
|
19880
|
+
`,
|
|
19881
|
+
`
|
|
19882
|
+
CREATE INDEX IF NOT EXISTS account_payment_retention_records_provider_idx
|
|
19883
|
+
ON account_payment_retention_records (provider, account_deleted_at DESC)
|
|
19884
|
+
`,
|
|
19885
|
+
`
|
|
19886
|
+
CREATE TABLE IF NOT EXISTS account_payment_provider_events (
|
|
19887
|
+
provider_event_key text PRIMARY KEY,
|
|
19888
|
+
analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
|
|
19889
|
+
organization_id_hash text NOT NULL,
|
|
19890
|
+
provider text NOT NULL,
|
|
19891
|
+
provider_event_id text NOT NULL,
|
|
19892
|
+
provider_event_type text NOT NULL,
|
|
19893
|
+
processed_at timestamptz NOT NULL,
|
|
19894
|
+
account_deleted_at timestamptz NOT NULL,
|
|
19895
|
+
recorded_at timestamptz NOT NULL DEFAULT now()
|
|
19896
|
+
)
|
|
19897
|
+
`,
|
|
19898
|
+
`
|
|
19899
|
+
CREATE UNIQUE INDEX IF NOT EXISTS account_payment_provider_events_provider_event_key
|
|
19900
|
+
ON account_payment_provider_events (provider, provider_event_id)
|
|
19901
|
+
`
|
|
19902
|
+
]
|
|
19431
19903
|
})
|
|
19432
19904
|
];
|
|
19433
19905
|
|
|
@@ -19631,7 +20103,7 @@ async function listLocalIncidents(input2, dependencies) {
|
|
|
19631
20103
|
return true;
|
|
19632
20104
|
}
|
|
19633
20105
|
return incident.status === input2.status;
|
|
19634
|
-
}).filter((incident) => input2.severity === void 0 ? true : incident.severity === input2.severity).sort(sortIncidentsDescending);
|
|
20106
|
+
}).filter((incident) => input2.severity === void 0 ? true : incident.severity === input2.severity).filter((incident) => input2.firstSeenAfter === void 0 ? true : incident.first_seen_at >= input2.firstSeenAfter).sort(sortIncidentsDescending);
|
|
19635
20107
|
const startIndex = input2.cursor === void 0 ? 0 : incidents.findIndex((incident) => buildCursor(incident) === input2.cursor) + 1;
|
|
19636
20108
|
const pagedIncidents = input2.limit === void 0 ? incidents.slice(startIndex) : incidents.slice(startIndex, startIndex + input2.limit);
|
|
19637
20109
|
const hasMore = input2.limit !== void 0 && startIndex + input2.limit < incidents.length;
|
|
@@ -20175,6 +20647,10 @@ var import_node_path9 = require("node:path");
|
|
|
20175
20647
|
|
|
20176
20648
|
// ../../packages/project-management-client/src/index.ts
|
|
20177
20649
|
var ProjectMetricsSchema = external_exports.object({
|
|
20650
|
+
open_incidents: external_exports.number().int().nonnegative().default(0),
|
|
20651
|
+
regressed_incidents: external_exports.number().int().nonnegative().default(0),
|
|
20652
|
+
opened_incidents_today: external_exports.number().int().nonnegative().default(0),
|
|
20653
|
+
opened_incidents_month: external_exports.number().int().nonnegative().default(0),
|
|
20178
20654
|
monthly_bundle_requests: external_exports.number().int().nonnegative(),
|
|
20179
20655
|
monthly_raw_ingested_events: external_exports.number().int().nonnegative(),
|
|
20180
20656
|
retained_bundles: external_exports.number().int().nonnegative(),
|
|
@@ -27189,6 +27665,7 @@ async function listAllCloudIncidents(input2, api) {
|
|
|
27189
27665
|
...input2.service === void 0 ? {} : { service: input2.service },
|
|
27190
27666
|
...input2.status === void 0 ? {} : { status: input2.status },
|
|
27191
27667
|
...input2.severity === void 0 ? {} : { severity: input2.severity },
|
|
27668
|
+
...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter },
|
|
27192
27669
|
...cursor === void 0 ? {} : { cursor }
|
|
27193
27670
|
});
|
|
27194
27671
|
incidents.push(
|
|
@@ -27209,7 +27686,8 @@ async function mapCombinedIncidentListResult(input2, api, dependencies) {
|
|
|
27209
27686
|
...input2.environment === void 0 ? {} : { environment: input2.environment },
|
|
27210
27687
|
...input2.service === void 0 ? {} : { service: input2.service },
|
|
27211
27688
|
...input2.status === void 0 ? {} : { status: input2.status },
|
|
27212
|
-
...input2.severity === void 0 ? {} : { severity: input2.severity }
|
|
27689
|
+
...input2.severity === void 0 ? {} : { severity: input2.severity },
|
|
27690
|
+
...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter }
|
|
27213
27691
|
},
|
|
27214
27692
|
dependencies
|
|
27215
27693
|
);
|
|
@@ -27220,7 +27698,8 @@ async function mapCombinedIncidentListResult(input2, api, dependencies) {
|
|
|
27220
27698
|
...input2.environment === void 0 ? {} : { environment: input2.environment },
|
|
27221
27699
|
...input2.service === void 0 ? {} : { service: input2.service },
|
|
27222
27700
|
...input2.status === void 0 ? {} : { status: input2.status },
|
|
27223
|
-
...input2.severity === void 0 ? {} : { severity: input2.severity }
|
|
27701
|
+
...input2.severity === void 0 ? {} : { severity: input2.severity },
|
|
27702
|
+
...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter }
|
|
27224
27703
|
},
|
|
27225
27704
|
api
|
|
27226
27705
|
);
|
|
@@ -27259,6 +27738,9 @@ async function listIncidentsCommand(input2, api) {
|
|
|
27259
27738
|
if (input2.severity !== void 0) {
|
|
27260
27739
|
requestInput.severity = input2.severity;
|
|
27261
27740
|
}
|
|
27741
|
+
if (input2.firstSeenAfter !== void 0) {
|
|
27742
|
+
requestInput.firstSeenAfter = input2.firstSeenAfter;
|
|
27743
|
+
}
|
|
27262
27744
|
if (input2.cursor !== void 0) {
|
|
27263
27745
|
requestInput.cursor = input2.cursor;
|
|
27264
27746
|
}
|
|
@@ -27290,6 +27772,7 @@ async function listIncidentsWithAuthCommand(input2, dependencies) {
|
|
|
27290
27772
|
...input2.service === void 0 ? {} : { service: input2.service },
|
|
27291
27773
|
...input2.status === void 0 ? {} : { status: input2.status },
|
|
27292
27774
|
...input2.severity === void 0 ? {} : { severity: input2.severity },
|
|
27775
|
+
...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter },
|
|
27293
27776
|
...input2.cursor === void 0 ? {} : { cursor: input2.cursor },
|
|
27294
27777
|
...input2.limit === void 0 ? {} : { limit: input2.limit }
|
|
27295
27778
|
},
|
|
@@ -27314,6 +27797,7 @@ async function listIncidentsWithAuthCommand(input2, dependencies) {
|
|
|
27314
27797
|
...input2.service === void 0 ? {} : { service: input2.service },
|
|
27315
27798
|
...input2.status === void 0 ? {} : { status: input2.status },
|
|
27316
27799
|
...input2.severity === void 0 ? {} : { severity: input2.severity },
|
|
27800
|
+
...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter },
|
|
27317
27801
|
...input2.cursor === void 0 ? {} : { cursor: input2.cursor },
|
|
27318
27802
|
...input2.limit === void 0 ? {} : { limit: input2.limit },
|
|
27319
27803
|
...input2.json === void 0 ? {} : { json: input2.json }
|
|
@@ -27349,6 +27833,9 @@ async function listIncidentsWithAuthCommand(input2, dependencies) {
|
|
|
27349
27833
|
if (input2.severity !== void 0) {
|
|
27350
27834
|
commandInput.severity = input2.severity;
|
|
27351
27835
|
}
|
|
27836
|
+
if (input2.firstSeenAfter !== void 0) {
|
|
27837
|
+
commandInput.firstSeenAfter = input2.firstSeenAfter;
|
|
27838
|
+
}
|
|
27352
27839
|
if (input2.cursor !== void 0) {
|
|
27353
27840
|
commandInput.cursor = input2.cursor;
|
|
27354
27841
|
}
|
|
@@ -29073,7 +29560,7 @@ var CLI_USAGE_LINES = [
|
|
|
29073
29560
|
" debugbundle login --github-device [--label <label>] [--base-url <url>] [--auth-file <path>] [--json]",
|
|
29074
29561
|
" debugbundle profile validate [--json]",
|
|
29075
29562
|
" debugbundle whoami [--auth-file <path>] [--json]",
|
|
29076
|
-
" debugbundle incidents [--source <local|cloud>] [--project-id <id>] [--environment <name>] [--service <name>] [--status <status>] [--severity <severity>] [--cursor <cursor>] [--limit <n>] [--auth-file <path>] [--json]",
|
|
29563
|
+
" debugbundle incidents [--source <local|cloud>] [--project-id <id>] [--environment <name>] [--service <name>] [--status <status>] [--severity <severity>] [--first-seen-after <ISO8601>] [--cursor <cursor>] [--limit <n>] [--auth-file <path>] [--json]",
|
|
29077
29564
|
" debugbundle inspect <incident-id> [--source <local|cloud>] [--auth-file <path>] [--json]",
|
|
29078
29565
|
" debugbundle explain <incident-id> [--source <local|cloud>] [--auth-file <path>] [--json]",
|
|
29079
29566
|
" debugbundle resolve <incident-id> [incident-id ...] [--source <local|cloud>] [--auth-file <path>] [--json]",
|
|
@@ -32379,18 +32866,44 @@ function mapErrorToExitCode12(error) {
|
|
|
32379
32866
|
}
|
|
32380
32867
|
return 1;
|
|
32381
32868
|
}
|
|
32382
|
-
function
|
|
32869
|
+
function formatMatcherFromValue(matcher) {
|
|
32383
32870
|
const parts = [];
|
|
32384
|
-
const matcher = rule.matcher;
|
|
32385
32871
|
if (matcher.event_types !== void 0) {
|
|
32386
32872
|
parts.push(`event_types=${matcher.event_types.join(",")}`);
|
|
32387
32873
|
}
|
|
32388
32874
|
if (matcher.browser_event_kind !== void 0) {
|
|
32389
32875
|
parts.push(`browser_event_kind=${matcher.browser_event_kind}`);
|
|
32390
32876
|
}
|
|
32877
|
+
if (matcher.browser_event_opaque !== void 0) {
|
|
32878
|
+
parts.push(`browser_event_opaque=${String(matcher.browser_event_opaque)}`);
|
|
32879
|
+
}
|
|
32880
|
+
if (matcher.client_kind !== void 0) {
|
|
32881
|
+
parts.push(`client_kind=${matcher.client_kind}`);
|
|
32882
|
+
}
|
|
32883
|
+
if (matcher.bot_family !== void 0) {
|
|
32884
|
+
parts.push(`bot_family=${matcher.bot_family}`);
|
|
32885
|
+
}
|
|
32886
|
+
if (matcher.services !== void 0) {
|
|
32887
|
+
parts.push(`services=${matcher.services.join(",")}`);
|
|
32888
|
+
}
|
|
32889
|
+
if (matcher.environments !== void 0) {
|
|
32890
|
+
parts.push(`environments=${matcher.environments.join(",")}`);
|
|
32891
|
+
}
|
|
32892
|
+
if (matcher.message_equals !== void 0) {
|
|
32893
|
+
parts.push(`message_equals=${JSON.stringify(matcher.message_equals)}`);
|
|
32894
|
+
}
|
|
32895
|
+
if (matcher.message_contains !== void 0) {
|
|
32896
|
+
parts.push(`message_contains=${JSON.stringify(matcher.message_contains)}`);
|
|
32897
|
+
}
|
|
32898
|
+
if (matcher.error_name !== void 0) {
|
|
32899
|
+
parts.push(`error_name=${matcher.error_name}`);
|
|
32900
|
+
}
|
|
32391
32901
|
if (matcher.resource_url?.host !== void 0) {
|
|
32392
32902
|
parts.push(`resource_host=${matcher.resource_url.host}`);
|
|
32393
32903
|
}
|
|
32904
|
+
if (matcher.resource_url?.path_equals !== void 0) {
|
|
32905
|
+
parts.push(`resource_path=${matcher.resource_url.path_equals}`);
|
|
32906
|
+
}
|
|
32394
32907
|
if (matcher.request_url?.path_equals !== void 0) {
|
|
32395
32908
|
parts.push(`request_path=${matcher.request_url.path_equals}`);
|
|
32396
32909
|
}
|
|
@@ -32402,6 +32915,9 @@ function formatMatcher(rule) {
|
|
|
32402
32915
|
}
|
|
32403
32916
|
return parts.length > 0 ? parts.join(" ") : "matcher=custom";
|
|
32404
32917
|
}
|
|
32918
|
+
function formatMatcher(rule) {
|
|
32919
|
+
return formatMatcherFromValue(rule.matcher);
|
|
32920
|
+
}
|
|
32405
32921
|
function formatRule(rule) {
|
|
32406
32922
|
const action = rule.action === "sample" ? `${rule.action}:${rule.sample_rate ?? "?"}:${rule.sample_event_class ?? "?"}` : rule.action;
|
|
32407
32923
|
return [
|
|
@@ -32422,7 +32938,10 @@ function formatSuggestionResponse(response) {
|
|
|
32422
32938
|
return response.suggestions.map(
|
|
32423
32939
|
(suggestion) => [
|
|
32424
32940
|
`${suggestion.suggestion_id} ${suggestion.recommended_action} ${suggestion.confidence} ${suggestion.label}`,
|
|
32425
|
-
suggestion.reason
|
|
32941
|
+
suggestion.reason,
|
|
32942
|
+
`matcher: ${formatMatcherFromValue(suggestion.rule.matcher)}`,
|
|
32943
|
+
`requires_confirmation: ${String(suggestion.requires_confirmation)}`,
|
|
32944
|
+
`apply: debugbundle capture-rule create-from-suggestion <incident-id> --suggestion-id ${suggestion.suggestion_id}`
|
|
32426
32945
|
].join("\n")
|
|
32427
32946
|
).join("\n\n");
|
|
32428
32947
|
}
|
|
@@ -34739,7 +35258,7 @@ async function handleCaptureRuleCommand2(parsedArgv, dependencies) {
|
|
|
34739
35258
|
// package.json
|
|
34740
35259
|
var package_default = {
|
|
34741
35260
|
name: "@debugbundle/cli",
|
|
34742
|
-
version: "1.
|
|
35261
|
+
version: "1.4.0",
|
|
34743
35262
|
private: false,
|
|
34744
35263
|
description: "Command-line interface for DebugBundle",
|
|
34745
35264
|
license: "AGPL-3.0-only",
|
|
@@ -35030,7 +35549,7 @@ ${formatUsage()}`
|
|
|
35030
35549
|
return await (dependencies.whoamiCommand ?? whoamiCommand)(appendCommonAuthOptions(parsedArgv, {}));
|
|
35031
35550
|
}
|
|
35032
35551
|
if (command === "incidents") {
|
|
35033
|
-
expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "source", "project-id", "environment", "service", "status", "severity", "cursor", "limit"]);
|
|
35552
|
+
expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "source", "project-id", "environment", "service", "status", "severity", "first-seen-after", "cursor", "limit"]);
|
|
35034
35553
|
ensureNoExtraPositionals(parsedArgv, 1);
|
|
35035
35554
|
const input2 = appendCommonAuthOptions(parsedArgv, {});
|
|
35036
35555
|
const source = readRetrievalSource(parsedArgv);
|
|
@@ -35057,6 +35576,10 @@ ${formatUsage()}`
|
|
|
35057
35576
|
if (severity !== void 0) {
|
|
35058
35577
|
input2.severity = severity;
|
|
35059
35578
|
}
|
|
35579
|
+
const firstSeenAfter = readStringOption(parsedArgv, "first-seen-after");
|
|
35580
|
+
if (firstSeenAfter !== void 0) {
|
|
35581
|
+
input2.firstSeenAfter = firstSeenAfter;
|
|
35582
|
+
}
|
|
35060
35583
|
const cursor = readStringOption(parsedArgv, "cursor");
|
|
35061
35584
|
if (cursor !== void 0) {
|
|
35062
35585
|
input2.cursor = cursor;
|