@debugbundle/cli 1.4.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.cjs +1523 -104
  2. package/package.json +1 -1
package/dist/main.cjs CHANGED
@@ -14462,6 +14462,113 @@ var coerce = {
14462
14462
  };
14463
14463
  var NEVER = INVALID;
14464
14464
 
14465
+ // ../../packages/shared-types/src/tier-capabilities.ts
14466
+ var TIER_CAPABILITIES = {
14467
+ free: {
14468
+ remote_probes: false,
14469
+ github_automation: false,
14470
+ slack_integration: false,
14471
+ cloud_improvement_bundles: false,
14472
+ shared_dashboards: false,
14473
+ member_invites: false,
14474
+ included_capacity_units: 1,
14475
+ max_members: 1,
14476
+ ingestion_rate_per_min: 1e3,
14477
+ retrieval_rate_per_min: 100,
14478
+ bundle_retention_days: 7,
14479
+ raw_event_retention_days: 7,
14480
+ // Allowance buckets (account-level pool, not per capacity unit)
14481
+ monthly_bundle_requests: 100,
14482
+ monthly_raw_ingested_events: 750,
14483
+ retained_bundle_cap: 50,
14484
+ monthly_remote_activations: 0,
14485
+ monthly_alert_deliveries: 25,
14486
+ monthly_webhook_deliveries: 100,
14487
+ availability_checks_per_project: 1,
14488
+ availability_check_min_interval_seconds: 300
14489
+ },
14490
+ solo: {
14491
+ remote_probes: true,
14492
+ github_automation: true,
14493
+ slack_integration: false,
14494
+ cloud_improvement_bundles: true,
14495
+ shared_dashboards: false,
14496
+ member_invites: false,
14497
+ included_capacity_units: 3,
14498
+ max_members: 1,
14499
+ ingestion_rate_per_min: 5e3,
14500
+ retrieval_rate_per_min: 300,
14501
+ bundle_retention_days: 30,
14502
+ raw_event_retention_days: 14,
14503
+ // Per-unit allowance (multiply by included and purchased capacity units)
14504
+ monthly_bundle_requests: 250,
14505
+ monthly_raw_ingested_events: 3500,
14506
+ retained_bundle_cap: 150,
14507
+ monthly_remote_activations: 25,
14508
+ monthly_alert_deliveries: 75,
14509
+ monthly_webhook_deliveries: 250,
14510
+ availability_checks_per_project: 5,
14511
+ availability_check_min_interval_seconds: 60
14512
+ },
14513
+ team: {
14514
+ remote_probes: true,
14515
+ github_automation: true,
14516
+ slack_integration: true,
14517
+ cloud_improvement_bundles: true,
14518
+ shared_dashboards: true,
14519
+ member_invites: true,
14520
+ included_capacity_units: 15,
14521
+ max_members: 1e3,
14522
+ ingestion_rate_per_min: 1e4,
14523
+ retrieval_rate_per_min: 500,
14524
+ bundle_retention_days: 90,
14525
+ raw_event_retention_days: 30,
14526
+ // Per-unit allowance (multiply by included and purchased capacity units)
14527
+ monthly_bundle_requests: 1e3,
14528
+ monthly_raw_ingested_events: 1e4,
14529
+ retained_bundle_cap: 400,
14530
+ monthly_remote_activations: 50,
14531
+ monthly_alert_deliveries: 300,
14532
+ monthly_webhook_deliveries: 1e3,
14533
+ availability_checks_per_project: 25,
14534
+ availability_check_min_interval_seconds: 30
14535
+ }
14536
+ };
14537
+ var SELFHOST_CAPABILITIES = {
14538
+ remote_probes: true,
14539
+ github_automation: true,
14540
+ slack_integration: true,
14541
+ cloud_improvement_bundles: true,
14542
+ shared_dashboards: true,
14543
+ member_invites: true,
14544
+ included_capacity_units: 1e6,
14545
+ max_members: 1e3,
14546
+ ingestion_rate_per_min: 1e6,
14547
+ retrieval_rate_per_min: 1e5,
14548
+ bundle_retention_days: 36500,
14549
+ raw_event_retention_days: 36500,
14550
+ monthly_bundle_requests: 1e9,
14551
+ monthly_raw_ingested_events: 1e9,
14552
+ retained_bundle_cap: 1e6,
14553
+ monthly_remote_activations: 1e6,
14554
+ monthly_alert_deliveries: 1e6,
14555
+ monthly_webhook_deliveries: 1e6,
14556
+ availability_checks_per_project: 1e6,
14557
+ availability_check_min_interval_seconds: 30
14558
+ };
14559
+ function isSelfHostMode() {
14560
+ return typeof process !== "undefined" && process.env["SELFHOST_MODE"] === "true";
14561
+ }
14562
+ function getTierCapabilities(plan) {
14563
+ if (isSelfHostMode()) {
14564
+ return SELFHOST_CAPABILITIES;
14565
+ }
14566
+ if (plan !== void 0 && plan in TIER_CAPABILITIES) {
14567
+ return TIER_CAPABILITIES[plan];
14568
+ }
14569
+ return TIER_CAPABILITIES.free;
14570
+ }
14571
+
14465
14572
  // ../../packages/shared-types/src/capture-policy.ts
14466
14573
  var EventClassValues = [
14467
14574
  "incident_signal",
@@ -14707,6 +14814,7 @@ function isRouteOnlyExternalProbe(normalizedRoute) {
14707
14814
  "/__debug__/render_panel",
14708
14815
  "/actuator",
14709
14816
  "/autodiscover/autodiscover.json",
14817
+ "/containers/json",
14710
14818
  "/developmentserver/metadatauploader",
14711
14819
  "/cpanel",
14712
14820
  "/favicon.ico",
@@ -15836,8 +15944,10 @@ function buildSkill() {
15836
15944
  "name: debugbundle",
15837
15945
  "description: >-",
15838
15946
  " Investigate runtime incidents, inspect debug bundles, generate reproductions,",
15839
- " and run improvement analysis using the DebugBundle CLI and local project scaffold.",
15840
- " Use when the user reports a bug, runtime failure, or asks about production incidents.",
15947
+ " run improvement analysis, and inspect operational controls using the DebugBundle",
15948
+ " CLI and local project scaffold. Use when the user reports a bug, runtime",
15949
+ " failure, production incident, endpoint downtime, health-check issue, missing",
15950
+ " notification, webhook delivery failure, probe request, or noisy incident.",
15841
15951
  "metadata:",
15842
15952
  " author: debugbundle",
15843
15953
  ' version: "1.0"',
@@ -15875,6 +15985,24 @@ function buildSkill() {
15875
15985
  "4. Apply the narrowest fix, then validate it with the repository test workflow from `.debugbundle/profile.json`.",
15876
15986
  "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.",
15877
15987
  "",
15988
+ "## Investigation Controls",
15989
+ "",
15990
+ "Use these controls when the user's issue is about observability behavior, notification delivery, targeted evidence gathering, or event noise rather than only application code.",
15991
+ "",
15992
+ "- Availability checks: use hosted health checks for endpoint downtime, public reachability, or project Health tab issues. These are DebugBundle-run external `GET`/`HEAD` checks, not SDK events from the customer app.",
15993
+ "- Probes: inspect active probes with `debugbundle probe list <project-id> --json` or MCP `list_active_probes` before activating more probes. Activate probes only when targeted runtime evidence is needed and the user has asked for investigation.",
15994
+ "- Capture policy and rules: inspect policy/rules before suppressing noisy incidents. Prefer `debugbundle capture-rule suggest <incident-id> --json` and narrow capture-policy path rules over broad drops or demotions.",
15995
+ "- Alerts and webhooks: when the user reports missing, duplicate, or failed notifications, inspect alert config, webhook config, and webhook delivery history before changing application code.",
15996
+ "",
15997
+ "## Availability Checks",
15998
+ "",
15999
+ "- Start with `debugbundle health checks list --project-id <id> --json` or MCP `list_health_checks` to inspect saved checks and plan limits.",
16000
+ "- For a failing check, inspect `debugbundle health checks results <check-id> --project-id <id> --json` and `debugbundle health checks daily-rollups <check-id> --project-id <id> --json` before changing code.",
16001
+ "- Use `debugbundle health checks test --project-id <id> --url <url> --json` or MCP `test_health_check` before creating or updating a saved check. Tests are side-effect-free: no incidents, retained history rows, or counters.",
16002
+ "- Create, update, delete, enable, or disable checks only when the user explicitly asks to change monitoring.",
16003
+ "- Availability incidents reuse the normal incident lifecycle. If a check opened an incident, fetch the incident context, bundle, and reproduction before proposing a fix, then resolve only after the endpoint recovers or the intentional verification incident has served its purpose.",
16004
+ "- Do not configure private, localhost, metadata-service, credentialed, or state-mutating targets. V1 health-check targets must be external `http`/`https` URLs on safe ports.",
16005
+ "",
15878
16006
  "## Incident Hygiene",
15879
16007
  "",
15880
16008
  "- Treat `open` as actionable work, not historical record.",
@@ -15891,6 +16019,25 @@ function buildSkill() {
15891
16019
  "- 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
16020
  "- 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
16021
  "",
16022
+ "## Notification Delivery",
16023
+ "",
16024
+ "When notification or automation delivery is the reported failure, inspect configuration and delivery records before changing incident logic.",
16025
+ "",
16026
+ "- Alerts route incident notifications to configured channels. Start with `debugbundle alert list --project-id <id> --json` and confirm condition, severity, service, cooldown, channel, and enabled state.",
16027
+ "- Webhooks deliver signed lifecycle events to external systems. Start with `debugbundle webhook list --project-id <id> --json`, then inspect `debugbundle webhook deliveries <webhook-id> --project-id <id> --json` before retrying or testing.",
16028
+ "- Webhook tests and retries are side-effecting delivery actions. Use them only when validating a destination or replaying an explicit failed delivery.",
16029
+ "",
16030
+ "## Full Documentation",
16031
+ "",
16032
+ "- CLI: `https://debugbundle.com/docs/cli`",
16033
+ "- MCP tools: `https://debugbundle.com/docs/mcp/tools`",
16034
+ "- Availability checks: `https://debugbundle.com/docs/availability-checks`",
16035
+ "- Probes: `https://debugbundle.com/docs/probes`",
16036
+ "- Capture policy and rules: `https://debugbundle.com/docs/capture-policy`",
16037
+ "- Alerts: `https://debugbundle.com/docs/alerts` and `https://debugbundle.com/docs/cli/alerts`",
16038
+ "- Webhooks: `https://debugbundle.com/docs/webhooks` and `https://debugbundle.com/docs/cli/webhooks`",
16039
+ "- API ingestion: `https://debugbundle.com/docs/api/ingestion`",
16040
+ "",
15894
16041
  "## Profile Validation",
15895
16042
  "",
15896
16043
  "Use this task after setup or whenever architecture changes make the static profile stale.",
@@ -15968,6 +16115,56 @@ function buildCliReference() {
15968
16115
  "",
15969
16116
  "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
16117
  "",
16118
+ "## Probes",
16119
+ "",
16120
+ "- `debugbundle probe activate <project-id> --label-pattern <pattern> [--service <name>] [--environment <name>] [--ttl-seconds <n>] [--trigger-ttl-seconds <n>] [--auth-file <path>] [--json]`",
16121
+ "- `debugbundle probe list <project-id> [--auth-file <path>] [--json]`",
16122
+ "- `debugbundle probe deactivate <project-id> <activation-id> [--auth-file <path>] [--json]`",
16123
+ "",
16124
+ "Use probes for targeted evidence gathering when bundle context is insufficient. Prefer narrow label patterns, scoped service/environment values, and explicit TTLs.",
16125
+ "",
16126
+ "## Notifications",
16127
+ "",
16128
+ "- `debugbundle alert list --project-id <id> [--limit <n>] [--auth-file <path>] [--json]`",
16129
+ "- `debugbundle alert create --project-id <id> --channel <channel> --condition <condition> [--service-id <id>] [--severity-min <level>] [--cooldown <seconds>] --config-json <json> [--is-enabled <true|false>] [--auth-file <path>] [--json]`",
16130
+ "- `debugbundle alert update <alert-id> --project-id <id> [--service-id <id|null>] [--channel <channel>] [--condition <condition>] [--severity-min <level|null>] [--cooldown <seconds>] [--config-json <json|null>] [--is-enabled <true|false>] [--auth-file <path>] [--json]`",
16131
+ "- `debugbundle alert delete <alert-id> --project-id <id> [--auth-file <path>] [--json]`",
16132
+ "- `debugbundle webhook list --project-id <id> [--limit <n>] [--auth-file <path>] [--json]`",
16133
+ "- `debugbundle webhook create --project-id <id> --url <url> --event <event[,event]> [--environment <env[,env]>] [--service <svc[,svc]>] [--severity-min <level>] [--bundle-type <type[,type]>] [--verification <true|false>] [--is-enabled <true|false>] [--auth-file <path>] [--json]`",
16134
+ "- `debugbundle webhook update <webhook-id> --project-id <id> [--url <url>] [--event <event[,event]>] [--environment <env[,env]>] [--service <svc[,svc]>] [--severity-min <level>] [--bundle-type <type[,type]>] [--verification <true|false>] [--is-enabled <true|false>] [--auth-file <path>] [--json]`",
16135
+ "- `debugbundle webhook delete <webhook-id> --project-id <id> [--auth-file <path>] [--json]`",
16136
+ "- `debugbundle webhook test <webhook-id> --project-id <id> [--event <verification.passed|verification.failed>] [--auth-file <path>] [--json]`",
16137
+ "- `debugbundle webhook deliveries <webhook-id> --project-id <id> [--limit <n>] [--auth-file <path>] [--json]`",
16138
+ "- `debugbundle webhook retry <webhook-id> <delivery-id> --project-id <id> [--auth-file <path>] [--json]`",
16139
+ "",
16140
+ "Use alert commands for notification routing and webhook commands for signed event delivery, delivery history, synthetic tests, and manual retries.",
16141
+ "",
16142
+ "## Availability Checks",
16143
+ "",
16144
+ "- `debugbundle health checks list --project-id <id> [--limit <n>] [--auth-file <path>] [--json]`",
16145
+ "- `debugbundle health checks get <check-id> --project-id <id> [--auth-file <path>] [--json]`",
16146
+ "- `debugbundle health checks create --project-id <id> --name <name> --url <url> --interval-seconds <n> [--method <GET|HEAD>] [--expected-status-min <code>] [--expected-status-max <code>] [--timeout-ms <n>] [--failure-threshold <n>] [--recovery-threshold <n>] [--environment <name>] [--service <name|null>] [--enabled <true|false>] [--auth-file <path>] [--json]`",
16147
+ "- `debugbundle health checks update <check-id> --project-id <id> [--name <name>] [--url <url>] [--method <GET|HEAD>] [--expected-status-min <code>] [--expected-status-max <code>] [--timeout-ms <n>] [--interval-seconds <n>] [--failure-threshold <n>] [--recovery-threshold <n>] [--environment <name>] [--service <name|null>] [--enabled <true|false>] [--auth-file <path>] [--json]`",
16148
+ "- `debugbundle health checks delete <check-id> --project-id <id> [--auth-file <path>] [--json]`",
16149
+ "- `debugbundle health checks test --project-id <id> --url <url> [--method <GET|HEAD>] [--expected-status-min <code>] [--expected-status-max <code>] [--timeout-ms <n>] [--auth-file <path>] [--json]`",
16150
+ "- `debugbundle health checks results <check-id> --project-id <id> [--limit <n>] [--auth-file <path>] [--json]`",
16151
+ "- `debugbundle health checks daily-rollups <check-id> --project-id <id> [--limit <n>] [--auth-file <path>] [--json]`",
16152
+ "",
16153
+ "Use availability-check commands for hosted endpoint reachability. Prefer `test` before saving a new target. `test` is side-effect-free and does not create incidents or retained history. Saved checks remain visible after downgrade, but checks beyond current count or interval limits pause until the project becomes eligible again.",
16154
+ "",
16155
+ "## Documentation URLs",
16156
+ "",
16157
+ "- CLI overview: `https://debugbundle.com/docs/cli`",
16158
+ "- Cloud workflow: `https://debugbundle.com/docs/cli/cloud-workflow`",
16159
+ "- API overview: `https://debugbundle.com/docs/api`",
16160
+ "- API ingestion: `https://debugbundle.com/docs/api/ingestion`",
16161
+ "- Alerts: `https://debugbundle.com/docs/alerts` and `https://debugbundle.com/docs/cli/alerts`",
16162
+ "- Webhooks: `https://debugbundle.com/docs/webhooks`, `https://debugbundle.com/docs/cli/webhooks`, and `https://debugbundle.com/docs/api/webhooks`",
16163
+ "- Probes: `https://debugbundle.com/docs/probes` and `https://debugbundle.com/docs/api/probes`",
16164
+ "- Capture policy and rules: `https://debugbundle.com/docs/capture-policy`",
16165
+ "- Availability checks: `https://debugbundle.com/docs/availability-checks`",
16166
+ "- MCP tool catalog: `https://debugbundle.com/docs/mcp/tools`",
16167
+ "",
15971
16168
  "## Operational Paths",
15972
16169
  "",
15973
16170
  "- `.debugbundle/profile.json` \u2014 committed project map and agent validation state",
@@ -15989,7 +16186,7 @@ function buildCliReference() {
15989
16186
  "",
15990
16187
  "```bash",
15991
16188
  "debugbundle incidents --status open --json",
15992
- "debugbundle resolve <incident-id>",
16189
+ "debugbundle resolve <incident-id> [incident-id ...]",
15993
16190
  "debugbundle incidents --status open --json",
15994
16191
  "```",
15995
16192
  "",
@@ -16034,6 +16231,45 @@ function buildMcpReference() {
16034
16231
  "",
16035
16232
  "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
16233
  "",
16234
+ "## Probe Tools",
16235
+ "",
16236
+ "- `activate_probe` \u2014 activate a remote probe pattern with optional service/environment scope and TTL.",
16237
+ "- `list_active_probes` \u2014 list active probe activations for a project.",
16238
+ "- `deactivate_probe` \u2014 deactivate one active probe.",
16239
+ "",
16240
+ "Use probes for targeted evidence gathering when incident bundles do not contain enough runtime context.",
16241
+ "",
16242
+ "## Notification Tools",
16243
+ "",
16244
+ "- `list_alerts`, `create_alert`, `update_alert`, `delete_alert` \u2014 manage incident alert rules.",
16245
+ "- `list_webhooks`, `create_webhook`, `update_webhook`, `delete_webhook` \u2014 manage signed webhook destinations.",
16246
+ "- `test_webhook`, `list_webhook_deliveries` \u2014 validate webhook delivery and inspect delivery history.",
16247
+ "",
16248
+ "Use these tools when the reported problem is missing, duplicate, delayed, disabled, or failed notification delivery.",
16249
+ "",
16250
+ "## Availability Check Tools",
16251
+ "",
16252
+ "- `list_health_checks` \u2014 list hosted health checks and plan limits for a project.",
16253
+ "- `get_health_check` \u2014 fetch one hosted health check by id.",
16254
+ "- `test_health_check` \u2014 run a side-effect-free target test without opening incidents or writing retained history.",
16255
+ "- `create_health_check`, `update_health_check`, `delete_health_check` \u2014 manage saved hosted health checks when the user explicitly asks to change monitoring.",
16256
+ "- `list_health_check_results` \u2014 inspect recent raw executions for one check.",
16257
+ "- `list_health_check_daily_rollups` \u2014 inspect retained per-day status history for one check.",
16258
+ "",
16259
+ "Use these tools for endpoint downtime, public reachability, and project Health tab issues. Start with list/results/rollups, use `test_health_check` before saving target changes, and inspect the linked normal incident bundle when failures crossed the configured threshold.",
16260
+ "",
16261
+ "## Documentation URLs",
16262
+ "",
16263
+ "- MCP overview: `https://debugbundle.com/docs/mcp`",
16264
+ "- MCP workflows: `https://debugbundle.com/docs/mcp/workflows`",
16265
+ "- MCP tools: `https://debugbundle.com/docs/mcp/tools`",
16266
+ "- Availability checks: `https://debugbundle.com/docs/availability-checks`",
16267
+ "- Probes: `https://debugbundle.com/docs/probes`",
16268
+ "- Capture policy and rules: `https://debugbundle.com/docs/capture-policy`",
16269
+ "- Alerts: `https://debugbundle.com/docs/alerts`",
16270
+ "- Webhooks: `https://debugbundle.com/docs/webhooks`",
16271
+ "- API ingestion: `https://debugbundle.com/docs/api/ingestion`",
16272
+ "",
16037
16273
  "## Smoke-Test Cleanup Recipe",
16038
16274
  "",
16039
16275
  '1. Call `list_incidents` with `status: "open"`.',
@@ -16168,6 +16404,15 @@ function buildSkillEvals() {
16168
16404
  "Use capture-policy path rules for known route-scoped 4xx incidents."
16169
16405
  ]
16170
16406
  },
16407
+ {
16408
+ name: "operational_controls_guidance",
16409
+ prompt: "The user reports missing webhook deliveries and asks whether probes or alerts are available. Confirm the skill points the agent to the relevant operational controls and docs.",
16410
+ expected_behavior: [
16411
+ "Inspect alert and webhook configuration plus webhook delivery history before changing application code.",
16412
+ "Use probes for targeted evidence gathering with narrow scope and TTL.",
16413
+ "Point to the full CLI, MCP, alerts, webhooks, probes, capture policy, availability checks, and ingestion documentation URLs."
16414
+ ]
16415
+ },
16171
16416
  {
16172
16417
  name: "artifact_path_discovery",
16173
16418
  prompt: "The user reports an unknown local runtime error. Confirm the skill tells the agent which DebugBundle paths and commands to inspect first.",
@@ -17464,6 +17709,16 @@ var DEFAULT_SESSION_LIFETIME_MS = 1e3 * 60 * 60 * 24 * 7;
17464
17709
  var DEFAULT_EMAIL_AUTH_CODE_LIFETIME_MS = 1e3 * 60 * 10;
17465
17710
  var DEFAULT_GITHUB_OAUTH_STATE_LIFETIME_MS = 1e3 * 60 * 10;
17466
17711
 
17712
+ // ../../packages/storage/src/availability-check-store-helpers.ts
17713
+ var TIER_CAPABILITIES_SQL = {
17714
+ free_limit: getTierCapabilities("free").availability_checks_per_project,
17715
+ solo_limit: getTierCapabilities("solo").availability_checks_per_project,
17716
+ team_limit: getTierCapabilities("team").availability_checks_per_project,
17717
+ free_interval: getTierCapabilities("free").availability_check_min_interval_seconds,
17718
+ solo_interval: getTierCapabilities("solo").availability_check_min_interval_seconds,
17719
+ team_interval: getTierCapabilities("team").availability_check_min_interval_seconds
17720
+ };
17721
+
17467
17722
  // ../../packages/storage/src/auth-rate-limiter.ts
17468
17723
  var import_ioredis = __toESM(require_built3(), 1);
17469
17724
 
@@ -17968,8 +18223,131 @@ function classifyEvent(eventType, logLevel, probeActivationId, payload, captureP
17968
18223
  var import_ioredis4 = __toESM(require_built3(), 1);
17969
18224
  var DEFAULT_PROCESSING_TIMEOUT_MS = 5 * 60 * 1e3;
17970
18225
 
17971
- // ../../packages/storage/src/schema-migrations.ts
17972
- var import_node_crypto2 = require("node:crypto");
18226
+ // ../../packages/storage/src/availability-check-bootstrap-statements.ts
18227
+ var AVAILABILITY_CHECK_BOOTSTRAP_STATEMENTS = [
18228
+ `
18229
+ CREATE TABLE availability_checks (
18230
+ id uuid PRIMARY KEY,
18231
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
18232
+ created_by_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
18233
+ name text NOT NULL,
18234
+ url text NOT NULL,
18235
+ method text NOT NULL CHECK (method IN ('GET', 'HEAD')),
18236
+ expected_status_min integer NOT NULL DEFAULT 200 CHECK (expected_status_min BETWEEN 100 AND 599),
18237
+ expected_status_max integer NOT NULL DEFAULT 399 CHECK (expected_status_max BETWEEN 100 AND 599),
18238
+ timeout_ms integer NOT NULL DEFAULT 5000 CHECK (timeout_ms BETWEEN 500 AND 5000),
18239
+ interval_seconds integer NOT NULL CHECK (interval_seconds >= 30),
18240
+ failure_threshold integer NOT NULL DEFAULT 3 CHECK (failure_threshold BETWEEN 1 AND 10),
18241
+ recovery_threshold integer NOT NULL DEFAULT 2 CHECK (recovery_threshold BETWEEN 1 AND 10),
18242
+ environment text NOT NULL DEFAULT 'production',
18243
+ service_name text,
18244
+ enabled boolean NOT NULL DEFAULT true,
18245
+ status text NOT NULL DEFAULT 'unknown' CHECK (status IN ('unknown', 'passing', 'failing')),
18246
+ consecutive_failures integer NOT NULL DEFAULT 0,
18247
+ consecutive_successes integer NOT NULL DEFAULT 0,
18248
+ linked_incident_id uuid REFERENCES incidents(id) ON DELETE SET NULL,
18249
+ last_checked_at timestamptz,
18250
+ next_check_at timestamptz,
18251
+ claimed_at timestamptz,
18252
+ last_result_status text CHECK (
18253
+ last_result_status IS NULL OR last_result_status IN (
18254
+ 'success',
18255
+ 'http_status_mismatch',
18256
+ 'timeout',
18257
+ 'dns_error',
18258
+ 'tls_error',
18259
+ 'connection_error',
18260
+ 'redirect_blocked',
18261
+ 'security_blocked',
18262
+ 'internal_error'
18263
+ )
18264
+ ),
18265
+ last_result_http_status integer,
18266
+ last_result_error_kind text,
18267
+ last_result_error_message text,
18268
+ last_result_duration_ms integer,
18269
+ deleted_at timestamptz,
18270
+ created_at timestamptz NOT NULL DEFAULT now(),
18271
+ updated_at timestamptz NOT NULL DEFAULT now()
18272
+ )
18273
+ `,
18274
+ `
18275
+ CREATE INDEX availability_checks_project_created_idx
18276
+ ON availability_checks (project_id, created_at DESC)
18277
+ `,
18278
+ `
18279
+ CREATE INDEX availability_checks_due_idx
18280
+ ON availability_checks (next_check_at, project_id)
18281
+ `,
18282
+ `
18283
+ CREATE INDEX availability_checks_claimed_idx
18284
+ ON availability_checks (claimed_at)
18285
+ `,
18286
+ `
18287
+ CREATE TABLE availability_check_results (
18288
+ id uuid PRIMARY KEY,
18289
+ check_id uuid NOT NULL REFERENCES availability_checks(id) ON DELETE CASCADE,
18290
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
18291
+ started_at timestamptz NOT NULL,
18292
+ completed_at timestamptz NOT NULL,
18293
+ duration_ms integer NOT NULL,
18294
+ status text NOT NULL CHECK (
18295
+ status IN (
18296
+ 'success',
18297
+ 'http_status_mismatch',
18298
+ 'timeout',
18299
+ 'dns_error',
18300
+ 'tls_error',
18301
+ 'connection_error',
18302
+ 'redirect_blocked',
18303
+ 'security_blocked',
18304
+ 'internal_error'
18305
+ )
18306
+ ),
18307
+ http_status integer,
18308
+ error_kind text,
18309
+ error_message text,
18310
+ redirect_count integer NOT NULL DEFAULT 0,
18311
+ checked_url_host text NOT NULL,
18312
+ checked_url_path text NOT NULL,
18313
+ final_url text NOT NULL,
18314
+ created_at timestamptz NOT NULL DEFAULT now()
18315
+ )
18316
+ `,
18317
+ `
18318
+ CREATE INDEX availability_check_results_check_started_idx
18319
+ ON availability_check_results (check_id, started_at DESC)
18320
+ `,
18321
+ `
18322
+ CREATE INDEX availability_check_results_project_started_idx
18323
+ ON availability_check_results (project_id, started_at DESC)
18324
+ `,
18325
+ `
18326
+ CREATE TABLE availability_check_daily_rollups (
18327
+ id uuid PRIMARY KEY,
18328
+ check_id uuid NOT NULL REFERENCES availability_checks(id) ON DELETE CASCADE,
18329
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
18330
+ day date NOT NULL,
18331
+ state text NOT NULL CHECK (state IN ('unknown', 'operational', 'degraded', 'down', 'paused')),
18332
+ total_checks integer NOT NULL DEFAULT 0,
18333
+ successful_checks integer NOT NULL DEFAULT 0,
18334
+ failed_checks integer NOT NULL DEFAULT 0,
18335
+ degraded_checks integer NOT NULL DEFAULT 0,
18336
+ avg_duration_ms integer,
18337
+ first_checked_at timestamptz,
18338
+ last_checked_at timestamptz,
18339
+ downtime_seconds integer NOT NULL DEFAULT 0,
18340
+ incident_ids uuid[] NOT NULL DEFAULT '{}'::uuid[],
18341
+ created_at timestamptz NOT NULL DEFAULT now(),
18342
+ updated_at timestamptz NOT NULL DEFAULT now(),
18343
+ UNIQUE (check_id, day)
18344
+ )
18345
+ `,
18346
+ `
18347
+ CREATE INDEX availability_check_daily_rollups_project_day_idx
18348
+ ON availability_check_daily_rollups (project_id, day DESC)
18349
+ `
18350
+ ];
17973
18351
 
17974
18352
  // ../../packages/storage/src/storage-bootstrap-statements.ts
17975
18353
  var STORAGE_BOOTSTRAP_STATEMENTS = [
@@ -18138,6 +18516,7 @@ var STORAGE_BOOTSTRAP_STATEMENTS = [
18138
18516
  user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
18139
18517
  organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
18140
18518
  session_token_hash text UNIQUE NOT NULL,
18519
+ auth_method text CHECK (auth_method IS NULL OR auth_method IN ('email_code', 'github_oauth')),
18141
18520
  created_at timestamptz NOT NULL DEFAULT now(),
18142
18521
  expires_at timestamptz NOT NULL,
18143
18522
  revoked_at timestamptz
@@ -19066,12 +19445,257 @@ var STORAGE_BOOTSTRAP_STATEMENTS = [
19066
19445
  `
19067
19446
  ];
19068
19447
 
19448
+ // ../../packages/storage/src/storage-bootstrap-all-statements.ts
19449
+ var STORAGE_BOOTSTRAP_STATEMENTS2 = [
19450
+ ...STORAGE_BOOTSTRAP_STATEMENTS,
19451
+ ...AVAILABILITY_CHECK_BOOTSTRAP_STATEMENTS
19452
+ ];
19453
+
19069
19454
  // ../../packages/storage/src/migrations.ts
19070
- var STORAGE_BOOTSTRAP_SQL = STORAGE_BOOTSTRAP_STATEMENTS.join(";\n\n");
19455
+ var STORAGE_BOOTSTRAP_SQL = STORAGE_BOOTSTRAP_STATEMENTS2.join(";\n\n");
19071
19456
 
19072
- // ../../packages/storage/src/schema-migrations.ts
19457
+ // ../../packages/storage/src/availability-check-schema-migrations.ts
19458
+ var import_node_crypto2 = require("node:crypto");
19459
+ function defineAvailabilityCheckStorageSchemaMigration(input2) {
19460
+ return {
19461
+ ...input2,
19462
+ checksum: (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify(input2)).digest("hex")
19463
+ };
19464
+ }
19465
+ var AVAILABILITY_CHECK_STORAGE_SCHEMA_MIGRATIONS = [
19466
+ defineAvailabilityCheckStorageSchemaMigration({
19467
+ id: "202606150001_add_availability_checks",
19468
+ description: "Add project-scoped availability checks, result history, and daily rollups.",
19469
+ statements: [
19470
+ `
19471
+ CREATE TABLE IF NOT EXISTS availability_checks (
19472
+ id uuid PRIMARY KEY,
19473
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
19474
+ created_by_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
19475
+ name text NOT NULL,
19476
+ url text NOT NULL,
19477
+ method text NOT NULL,
19478
+ expected_status_min integer NOT NULL DEFAULT 200,
19479
+ expected_status_max integer NOT NULL DEFAULT 399,
19480
+ timeout_ms integer NOT NULL DEFAULT 5000,
19481
+ interval_seconds integer NOT NULL,
19482
+ failure_threshold integer NOT NULL DEFAULT 3,
19483
+ recovery_threshold integer NOT NULL DEFAULT 2,
19484
+ environment text NOT NULL DEFAULT 'production',
19485
+ service_name text,
19486
+ enabled boolean NOT NULL DEFAULT true,
19487
+ status text NOT NULL DEFAULT 'unknown',
19488
+ consecutive_failures integer NOT NULL DEFAULT 0,
19489
+ consecutive_successes integer NOT NULL DEFAULT 0,
19490
+ linked_incident_id uuid REFERENCES incidents(id) ON DELETE SET NULL,
19491
+ last_checked_at timestamptz,
19492
+ next_check_at timestamptz,
19493
+ claimed_at timestamptz,
19494
+ last_result_status text,
19495
+ last_result_http_status integer,
19496
+ last_result_error_kind text,
19497
+ last_result_error_message text,
19498
+ last_result_duration_ms integer,
19499
+ deleted_at timestamptz,
19500
+ created_at timestamptz NOT NULL DEFAULT now(),
19501
+ updated_at timestamptz NOT NULL DEFAULT now()
19502
+ )
19503
+ `,
19504
+ `
19505
+ ALTER TABLE availability_checks
19506
+ DROP CONSTRAINT IF EXISTS availability_checks_method_check
19507
+ `,
19508
+ `
19509
+ ALTER TABLE availability_checks
19510
+ ADD CONSTRAINT availability_checks_method_check
19511
+ CHECK (method IN ('GET', 'HEAD'))
19512
+ `,
19513
+ `
19514
+ ALTER TABLE availability_checks
19515
+ DROP CONSTRAINT IF EXISTS availability_checks_expected_status_min_check
19516
+ `,
19517
+ `
19518
+ ALTER TABLE availability_checks
19519
+ ADD CONSTRAINT availability_checks_expected_status_min_check
19520
+ CHECK (expected_status_min BETWEEN 100 AND 599)
19521
+ `,
19522
+ `
19523
+ ALTER TABLE availability_checks
19524
+ DROP CONSTRAINT IF EXISTS availability_checks_expected_status_max_check
19525
+ `,
19526
+ `
19527
+ ALTER TABLE availability_checks
19528
+ ADD CONSTRAINT availability_checks_expected_status_max_check
19529
+ CHECK (expected_status_max BETWEEN 100 AND 599)
19530
+ `,
19531
+ `
19532
+ ALTER TABLE availability_checks
19533
+ DROP CONSTRAINT IF EXISTS availability_checks_timeout_ms_check
19534
+ `,
19535
+ `
19536
+ ALTER TABLE availability_checks
19537
+ ADD CONSTRAINT availability_checks_timeout_ms_check
19538
+ CHECK (timeout_ms BETWEEN 500 AND 5000)
19539
+ `,
19540
+ `
19541
+ ALTER TABLE availability_checks
19542
+ DROP CONSTRAINT IF EXISTS availability_checks_interval_seconds_check
19543
+ `,
19544
+ `
19545
+ ALTER TABLE availability_checks
19546
+ ADD CONSTRAINT availability_checks_interval_seconds_check
19547
+ CHECK (interval_seconds >= 30)
19548
+ `,
19549
+ `
19550
+ ALTER TABLE availability_checks
19551
+ DROP CONSTRAINT IF EXISTS availability_checks_failure_threshold_check
19552
+ `,
19553
+ `
19554
+ ALTER TABLE availability_checks
19555
+ ADD CONSTRAINT availability_checks_failure_threshold_check
19556
+ CHECK (failure_threshold BETWEEN 1 AND 10)
19557
+ `,
19558
+ `
19559
+ ALTER TABLE availability_checks
19560
+ DROP CONSTRAINT IF EXISTS availability_checks_recovery_threshold_check
19561
+ `,
19562
+ `
19563
+ ALTER TABLE availability_checks
19564
+ ADD CONSTRAINT availability_checks_recovery_threshold_check
19565
+ CHECK (recovery_threshold BETWEEN 1 AND 10)
19566
+ `,
19567
+ `
19568
+ ALTER TABLE availability_checks
19569
+ DROP CONSTRAINT IF EXISTS availability_checks_status_check
19570
+ `,
19571
+ `
19572
+ ALTER TABLE availability_checks
19573
+ ADD CONSTRAINT availability_checks_status_check
19574
+ CHECK (status IN ('unknown', 'passing', 'failing'))
19575
+ `,
19576
+ `
19577
+ ALTER TABLE availability_checks
19578
+ DROP CONSTRAINT IF EXISTS availability_checks_last_result_status_check
19579
+ `,
19580
+ `
19581
+ ALTER TABLE availability_checks
19582
+ ADD CONSTRAINT availability_checks_last_result_status_check
19583
+ CHECK (
19584
+ last_result_status IS NULL OR last_result_status IN (
19585
+ 'success',
19586
+ 'http_status_mismatch',
19587
+ 'timeout',
19588
+ 'dns_error',
19589
+ 'tls_error',
19590
+ 'connection_error',
19591
+ 'redirect_blocked',
19592
+ 'security_blocked',
19593
+ 'internal_error'
19594
+ )
19595
+ )
19596
+ `,
19597
+ `
19598
+ CREATE INDEX IF NOT EXISTS availability_checks_project_created_idx
19599
+ ON availability_checks (project_id, created_at DESC)
19600
+ `,
19601
+ `
19602
+ CREATE INDEX IF NOT EXISTS availability_checks_due_idx
19603
+ ON availability_checks (next_check_at, project_id)
19604
+ `,
19605
+ `
19606
+ CREATE INDEX IF NOT EXISTS availability_checks_claimed_idx
19607
+ ON availability_checks (claimed_at)
19608
+ `,
19609
+ `
19610
+ CREATE TABLE IF NOT EXISTS availability_check_results (
19611
+ id uuid PRIMARY KEY,
19612
+ check_id uuid NOT NULL REFERENCES availability_checks(id) ON DELETE CASCADE,
19613
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
19614
+ started_at timestamptz NOT NULL,
19615
+ completed_at timestamptz NOT NULL,
19616
+ duration_ms integer NOT NULL,
19617
+ status text NOT NULL,
19618
+ http_status integer,
19619
+ error_kind text,
19620
+ error_message text,
19621
+ redirect_count integer NOT NULL DEFAULT 0,
19622
+ checked_url_host text NOT NULL,
19623
+ checked_url_path text NOT NULL,
19624
+ final_url text NOT NULL,
19625
+ created_at timestamptz NOT NULL DEFAULT now()
19626
+ )
19627
+ `,
19628
+ `
19629
+ ALTER TABLE availability_check_results
19630
+ DROP CONSTRAINT IF EXISTS availability_check_results_status_check
19631
+ `,
19632
+ `
19633
+ ALTER TABLE availability_check_results
19634
+ ADD CONSTRAINT availability_check_results_status_check
19635
+ CHECK (
19636
+ status IN (
19637
+ 'success',
19638
+ 'http_status_mismatch',
19639
+ 'timeout',
19640
+ 'dns_error',
19641
+ 'tls_error',
19642
+ 'connection_error',
19643
+ 'redirect_blocked',
19644
+ 'security_blocked',
19645
+ 'internal_error'
19646
+ )
19647
+ )
19648
+ `,
19649
+ `
19650
+ CREATE INDEX IF NOT EXISTS availability_check_results_check_started_idx
19651
+ ON availability_check_results (check_id, started_at DESC)
19652
+ `,
19653
+ `
19654
+ CREATE INDEX IF NOT EXISTS availability_check_results_project_started_idx
19655
+ ON availability_check_results (project_id, started_at DESC)
19656
+ `,
19657
+ `
19658
+ CREATE TABLE IF NOT EXISTS availability_check_daily_rollups (
19659
+ id uuid PRIMARY KEY,
19660
+ check_id uuid NOT NULL REFERENCES availability_checks(id) ON DELETE CASCADE,
19661
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
19662
+ day date NOT NULL,
19663
+ state text NOT NULL,
19664
+ total_checks integer NOT NULL DEFAULT 0,
19665
+ successful_checks integer NOT NULL DEFAULT 0,
19666
+ failed_checks integer NOT NULL DEFAULT 0,
19667
+ degraded_checks integer NOT NULL DEFAULT 0,
19668
+ avg_duration_ms integer,
19669
+ first_checked_at timestamptz,
19670
+ last_checked_at timestamptz,
19671
+ downtime_seconds integer NOT NULL DEFAULT 0,
19672
+ incident_ids uuid[] NOT NULL DEFAULT '{}'::uuid[],
19673
+ created_at timestamptz NOT NULL DEFAULT now(),
19674
+ updated_at timestamptz NOT NULL DEFAULT now(),
19675
+ UNIQUE (check_id, day)
19676
+ )
19677
+ `,
19678
+ `
19679
+ ALTER TABLE availability_check_daily_rollups
19680
+ DROP CONSTRAINT IF EXISTS availability_check_daily_rollups_state_check
19681
+ `,
19682
+ `
19683
+ ALTER TABLE availability_check_daily_rollups
19684
+ ADD CONSTRAINT availability_check_daily_rollups_state_check
19685
+ CHECK (state IN ('unknown', 'operational', 'degraded', 'down', 'paused'))
19686
+ `,
19687
+ `
19688
+ CREATE INDEX IF NOT EXISTS availability_check_daily_rollups_project_day_idx
19689
+ ON availability_check_daily_rollups (project_id, day DESC)
19690
+ `
19691
+ ]
19692
+ })
19693
+ ];
19694
+
19695
+ // ../../packages/storage/src/schema-migrations-catalog.ts
19696
+ var import_node_crypto3 = require("node:crypto");
19073
19697
  function computeMigrationChecksum(input2) {
19074
- return (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify(input2)).digest("hex");
19698
+ return (0, import_node_crypto3.createHash)("sha256").update(JSON.stringify(input2)).digest("hex");
19075
19699
  }
19076
19700
  function defineStorageSchemaMigration(input2) {
19077
19701
  return {
@@ -19900,9 +20524,41 @@ var STORAGE_SCHEMA_MIGRATIONS = [
19900
20524
  ON account_payment_provider_events (provider, provider_event_id)
19901
20525
  `
19902
20526
  ]
20527
+ }),
20528
+ defineStorageSchemaMigration({
20529
+ id: "202606120001_add_session_auth_method",
20530
+ description: "Track the auth method used to create each browser session.",
20531
+ statements: [
20532
+ "ALTER TABLE sessions ADD COLUMN IF NOT EXISTS auth_method text",
20533
+ "ALTER TABLE sessions DROP CONSTRAINT IF EXISTS sessions_auth_method_check",
20534
+ `
20535
+ ALTER TABLE sessions
20536
+ ADD CONSTRAINT sessions_auth_method_check
20537
+ CHECK (auth_method IS NULL OR auth_method IN ('email_code', 'github_oauth'))
20538
+ `
20539
+ ]
20540
+ }),
20541
+ defineStorageSchemaMigration({
20542
+ id: "202606130001_retire_expired_project_invites",
20543
+ description: "Retire already-expired project invites so re-inviting the same email is unblocked.",
20544
+ statements: [
20545
+ `
20546
+ UPDATE project_invites
20547
+ SET canceled_at = expires_at
20548
+ WHERE accepted_at IS NULL
20549
+ AND canceled_at IS NULL
20550
+ AND expires_at <= now()
20551
+ `
20552
+ ]
19903
20553
  })
19904
20554
  ];
19905
20555
 
20556
+ // ../../packages/storage/src/schema-migrations.ts
20557
+ var STORAGE_SCHEMA_MIGRATIONS2 = [
20558
+ ...STORAGE_SCHEMA_MIGRATIONS,
20559
+ ...AVAILABILITY_CHECK_STORAGE_SCHEMA_MIGRATIONS
20560
+ ];
20561
+
19906
20562
  // src/local-retrieval-store.ts
19907
20563
  var CONNECTION_FILE_PATH2 = ".debugbundle/local/connection.json";
19908
20564
  var STATE_FILE_PATH = ".debugbundle/local/state.json";
@@ -23886,12 +24542,12 @@ async function doctorCommand(input2, dependencies = {}) {
23886
24542
  }
23887
24543
 
23888
24544
  // src/ingest-command.ts
23889
- var import_node_crypto5 = require("node:crypto");
24545
+ var import_node_crypto6 = require("node:crypto");
23890
24546
  var import_promises11 = require("node:fs/promises");
23891
24547
  var import_node_path12 = require("node:path");
23892
24548
 
23893
24549
  // ../../packages/log-parser/src/project-id.ts
23894
- var import_node_crypto3 = require("node:crypto");
24550
+ var import_node_crypto4 = require("node:crypto");
23895
24551
  var INGEST_SDK = {
23896
24552
  name: "debugbundle-ingest",
23897
24553
  version: "0.1.0"
@@ -23901,7 +24557,7 @@ function slugify(value) {
23901
24557
  return normalized.length > 0 ? normalized : "application";
23902
24558
  }
23903
24559
  function buildDeterministicUuid(parts) {
23904
- const digest = (0, import_node_crypto3.createHash)("sha256").update(parts.join("\0")).digest();
24560
+ const digest = (0, import_node_crypto4.createHash)("sha256").update(parts.join("\0")).digest();
23905
24561
  const bytes = Uint8Array.from(digest.subarray(0, 16));
23906
24562
  bytes[6] = (bytes[6] ?? 0) & 15 | 80;
23907
24563
  bytes[8] = (bytes[8] ?? 0) & 63 | 128;
@@ -24206,7 +24862,7 @@ function parseLogFile(content, input2) {
24206
24862
  }
24207
24863
 
24208
24864
  // src/process-command.ts
24209
- var import_node_crypto4 = require("node:crypto");
24865
+ var import_node_crypto5 = require("node:crypto");
24210
24866
  var import_promises10 = require("node:fs/promises");
24211
24867
  var import_node_path11 = require("node:path");
24212
24868
 
@@ -25380,7 +26036,7 @@ function mergeAggregateGroup(aggregates) {
25380
26036
  });
25381
26037
  }
25382
26038
  function hashIdentifier(parts, prefix, length) {
25383
- const digest = (0, import_node_crypto4.createHash)("sha256").update(parts.join("\0")).digest("hex");
26039
+ const digest = (0, import_node_crypto5.createHash)("sha256").update(parts.join("\0")).digest("hex");
25384
26040
  return `${prefix}_${digest.slice(0, length)}`;
25385
26041
  }
25386
26042
  function deriveIncidentId(projectId, serviceName, environment, incidentFingerprint) {
@@ -25414,7 +26070,7 @@ function stableJson3(value) {
25414
26070
  return `{${keys.map((key) => `${JSON.stringify(key)}:${stableJson3(record[key])}`).join(",")}}`;
25415
26071
  }
25416
26072
  function buildRequestAnomalyFingerprint(input2) {
25417
- return (0, import_node_crypto4.createHash)("sha256").update(
26073
+ return (0, import_node_crypto5.createHash)("sha256").update(
25418
26074
  stableJson3({
25419
26075
  kind: "request_status_anomaly",
25420
26076
  project_id: input2.projectId,
@@ -26048,7 +26704,7 @@ function buildEventFileName(events, filePath) {
26048
26704
  const candidate = Date.parse(event.occurred_at);
26049
26705
  return Number.isFinite(candidate) && candidate > latest ? candidate : latest;
26050
26706
  }, 0);
26051
- const digest = (0, import_node_crypto5.createHash)("sha256").update([filePath, ...events.map((event) => event.event_id)].join("\0")).digest("hex").slice(0, 8);
26707
+ const digest = (0, import_node_crypto6.createHash)("sha256").update([filePath, ...events.map((event) => event.event_id)].join("\0")).digest("hex").slice(0, 8);
26052
26708
  return `${lastOccurredAt}-${digest}-${slugify2(events[0]?.service.name ?? (0, import_node_path12.basename)(filePath))}.events.json`;
26053
26709
  }
26054
26710
  function formatHumanOutput(summary) {
@@ -27103,7 +27759,7 @@ function buildManagedAgentsSection() {
27103
27759
  "- Read `.agents/skills/debugbundle/SKILL.md` for the full debugging workflow.",
27104
27760
  "- Use `debugbundle inspect <incident-id>` or MCP `get_bundle` when a user reports an issue.",
27105
27761
  "- Run reproduction artifacts from `.debugbundle/bundles/local/reproductions/` before proposing a fix.",
27106
- "- After a fix is verified, or after an intentional smoke or dogfood incident has served its purpose, resolve it with `debugbundle resolve <incident-id>` or MCP `resolve_incident` so open incidents remain actionable.",
27762
+ "- After a fix is verified, or after an intentional smoke or dogfood incident has served its purpose, resolve it with `debugbundle resolve <incident-id> [incident-id ...]` or MCP `resolve_incident` / `resolve_incidents` so open incidents remain actionable.",
27107
27763
  "- Use `debugbundle doctor` to validate local DebugBundle setup or connectivity issues.",
27108
27764
  MANAGED_AGENTS_END
27109
27765
  ].join("\n");
@@ -28596,7 +29252,7 @@ async function listServicesWithAuthCommand(input2, dependencies) {
28596
29252
  }
28597
29253
 
28598
29254
  // src/verify-command.ts
28599
- var import_node_crypto6 = require("node:crypto");
29255
+ var import_node_crypto7 = require("node:crypto");
28600
29256
  var import_promises15 = require("node:fs/promises");
28601
29257
  var import_node_path17 = require("node:path");
28602
29258
  function resolveOverallStatus2(checks) {
@@ -28741,7 +29397,7 @@ function cloudVerificationRunId(now) {
28741
29397
  return now.toISOString().replace(/[-:.TZ]/g, "").slice(0, 14);
28742
29398
  }
28743
29399
  function defaultCloudVerificationSuffix() {
28744
- return (0, import_node_crypto6.randomUUID)().replace(/-/g, "").slice(0, 12);
29400
+ return (0, import_node_crypto7.randomUUID)().replace(/-/g, "").slice(0, 12);
28745
29401
  }
28746
29402
  function normalizeCloudVerificationSuffix(suffix) {
28747
29403
  const normalized = suffix.toLowerCase().replace(/[^a-z0-9]/g, "").slice(0, 12);
@@ -29633,6 +30289,14 @@ var CLI_USAGE_LINES = [
29633
30289
  " debugbundle probe activate <project-id> --label-pattern <pattern> [--service <name>] [--environment <name>] [--ttl-seconds <n>] [--trigger-ttl-seconds <n>] [--auth-file <path>] [--json]",
29634
30290
  " debugbundle probe list <project-id> [--auth-file <path>] [--json]",
29635
30291
  " debugbundle probe deactivate <project-id> <activation-id> [--auth-file <path>] [--json]",
30292
+ " debugbundle health checks list --project-id <id> [--limit <n>] [--auth-file <path>] [--json]",
30293
+ " debugbundle health checks get <check-id> --project-id <id> [--auth-file <path>] [--json]",
30294
+ " debugbundle health checks create --project-id <id> --name <name> --url <url> --interval-seconds <n> [--method <GET|HEAD>] [--expected-status-min <code>] [--expected-status-max <code>] [--timeout-ms <n>] [--failure-threshold <n>] [--recovery-threshold <n>] [--environment <name>] [--service <name|null>] [--enabled <true|false>] [--auth-file <path>] [--json]",
30295
+ " debugbundle health checks update <check-id> --project-id <id> [--name <name>] [--url <url>] [--method <GET|HEAD>] [--expected-status-min <code>] [--expected-status-max <code>] [--timeout-ms <n>] [--interval-seconds <n>] [--failure-threshold <n>] [--recovery-threshold <n>] [--environment <name>] [--service <name|null>] [--enabled <true|false>] [--auth-file <path>] [--json]",
30296
+ " debugbundle health checks delete <check-id> --project-id <id> [--auth-file <path>] [--json]",
30297
+ " debugbundle health checks test --project-id <id> --url <url> [--method <GET|HEAD>] [--expected-status-min <code>] [--expected-status-max <code>] [--timeout-ms <n>] [--auth-file <path>] [--json]",
30298
+ " debugbundle health checks results <check-id> --project-id <id> [--limit <n>] [--auth-file <path>] [--json]",
30299
+ " debugbundle health checks daily-rollups <check-id> --project-id <id> [--limit <n>] [--auth-file <path>] [--json]",
29636
30300
  " debugbundle project members list --project-id <id> [--auth-file <path>] [--json]",
29637
30301
  " debugbundle project members invites --project-id <id> [--auth-file <path>] [--json]",
29638
30302
  " debugbundle project members invite --project-id <id> --email <email> --role <admin|member> [--auth-file <path>] [--json]",
@@ -32521,57 +33185,809 @@ async function handleTokenCommand(parsedArgv, dependencies) {
32521
33185
  throw new CliInputError("Unknown token command.");
32522
33186
  }
32523
33187
 
32524
- // src/capture-policy-commands.ts
32525
- var CapturePolicyApiError = class extends Error {
33188
+ // src/health-check-commands.ts
33189
+ var HealthCheckApiError = class extends Error {
32526
33190
  status;
32527
- constructor(status, message) {
32528
- super(message);
32529
- this.name = "CapturePolicyApiError";
33191
+ code;
33192
+ constructor(status, code) {
33193
+ super(`health_check_api_error: ${status}:${code}`);
33194
+ this.name = "HealthCheckApiError";
32530
33195
  this.status = status;
33196
+ this.code = code;
32531
33197
  }
32532
33198
  };
32533
- function toApiError3(status, body, fallback) {
33199
+ function toApiError3(status, body) {
32534
33200
  if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
32535
- return new CapturePolicyApiError(status, body.error);
33201
+ return new HealthCheckApiError(status, body.error);
32536
33202
  }
32537
- return new CapturePolicyApiError(status, fallback);
33203
+ return new HealthCheckApiError(status, "unknown_error");
32538
33204
  }
32539
- function createCapturePolicyApi(httpClient) {
32540
- return {
32541
- async getCapturePolicy(input2) {
32542
- const response = await httpClient.request({
32543
- method: "GET",
32544
- path: `/v1/projects/${encodeURIComponent(input2.projectId)}/capture-policy`,
32545
- bearerToken: input2.bearerToken
32546
- });
32547
- if (response.status !== 200) {
32548
- throw toApiError3(response.status, response.body, "Failed to get capture policy.");
32549
- }
32550
- const parsed = CapturePolicyResponseSchema.safeParse(response.body);
32551
- if (!parsed.success) {
32552
- throw new CapturePolicyApiError(500, "Invalid capture policy response.");
32553
- }
32554
- return parsed.data;
32555
- },
32556
- async updateCapturePolicy(input2) {
32557
- const response = await httpClient.request({
32558
- method: "PATCH",
32559
- path: `/v1/projects/${encodeURIComponent(input2.projectId)}/capture-policy`,
32560
- bearerToken: input2.bearerToken,
32561
- body: input2.update
32562
- });
32563
- if (response.status !== 200) {
32564
- throw toApiError3(response.status, response.body, "Failed to update capture policy.");
32565
- }
32566
- const parsed = CapturePolicyResponseSchema.safeParse(response.body);
32567
- if (!parsed.success) {
33205
+ function mapErrorToExitCode11(error) {
33206
+ if (!(error instanceof HealthCheckApiError)) {
33207
+ return 1;
33208
+ }
33209
+ if (error.status === 401) {
33210
+ return 2;
33211
+ }
33212
+ if (error.status === 404) {
33213
+ return 3;
33214
+ }
33215
+ if (error.status === 400) {
33216
+ return 4;
33217
+ }
33218
+ if (error.status === 403 || error.status === 409) {
33219
+ return 5;
33220
+ }
33221
+ if (error.status === 429) {
33222
+ return 6;
33223
+ }
33224
+ return 1;
33225
+ }
33226
+ function buildCreateRequestBody(input2) {
33227
+ const body = {
33228
+ name: input2.name,
33229
+ url: input2.url,
33230
+ method: input2.method,
33231
+ expected_status_min: input2.expectedStatusMin,
33232
+ expected_status_max: input2.expectedStatusMax,
33233
+ timeout_ms: input2.timeoutMs,
33234
+ interval_seconds: input2.intervalSeconds,
33235
+ failure_threshold: input2.failureThreshold,
33236
+ recovery_threshold: input2.recoveryThreshold,
33237
+ enabled: input2.enabled
33238
+ };
33239
+ if (input2.environment !== void 0) {
33240
+ body["environment"] = input2.environment;
33241
+ }
33242
+ if (input2.serviceName !== void 0) {
33243
+ body["service_name"] = input2.serviceName;
33244
+ }
33245
+ return body;
33246
+ }
33247
+ function buildUpdateRequestBody(input2) {
33248
+ const body = {};
33249
+ if (input2.name !== void 0) {
33250
+ body["name"] = input2.name;
33251
+ }
33252
+ if (input2.url !== void 0) {
33253
+ body["url"] = input2.url;
33254
+ }
33255
+ if (input2.method !== void 0) {
33256
+ body["method"] = input2.method;
33257
+ }
33258
+ if (input2.expectedStatusMin !== void 0) {
33259
+ body["expected_status_min"] = input2.expectedStatusMin;
33260
+ }
33261
+ if (input2.expectedStatusMax !== void 0) {
33262
+ body["expected_status_max"] = input2.expectedStatusMax;
33263
+ }
33264
+ if (input2.timeoutMs !== void 0) {
33265
+ body["timeout_ms"] = input2.timeoutMs;
33266
+ }
33267
+ if (input2.intervalSeconds !== void 0) {
33268
+ body["interval_seconds"] = input2.intervalSeconds;
33269
+ }
33270
+ if (input2.failureThreshold !== void 0) {
33271
+ body["failure_threshold"] = input2.failureThreshold;
33272
+ }
33273
+ if (input2.recoveryThreshold !== void 0) {
33274
+ body["recovery_threshold"] = input2.recoveryThreshold;
33275
+ }
33276
+ if (input2.environment !== void 0) {
33277
+ body["environment"] = input2.environment;
33278
+ }
33279
+ if (input2.serviceName !== void 0) {
33280
+ body["service_name"] = input2.serviceName;
33281
+ }
33282
+ if (input2.enabled !== void 0) {
33283
+ body["enabled"] = input2.enabled;
33284
+ }
33285
+ return body;
33286
+ }
33287
+ function createHealthCheckApi(httpClient) {
33288
+ return {
33289
+ async listHealthChecks(input2) {
33290
+ const limit = input2.limit ?? 100;
33291
+ const response = await httpClient.request({
33292
+ method: "GET",
33293
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks?limit=${encodeURIComponent(String(limit))}`,
33294
+ bearerToken: input2.bearerToken
33295
+ });
33296
+ if (response.status !== 200) {
33297
+ throw toApiError3(response.status, response.body);
33298
+ }
33299
+ return response.body;
33300
+ },
33301
+ async getHealthCheck(input2) {
33302
+ const response = await httpClient.request({
33303
+ method: "GET",
33304
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks/${encodeURIComponent(input2.checkId)}`,
33305
+ bearerToken: input2.bearerToken
33306
+ });
33307
+ if (response.status !== 200) {
33308
+ throw toApiError3(response.status, response.body);
33309
+ }
33310
+ return response.body;
33311
+ },
33312
+ async createHealthCheck(input2) {
33313
+ const response = await httpClient.request({
33314
+ method: "POST",
33315
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks`,
33316
+ bearerToken: input2.bearerToken,
33317
+ body: buildCreateRequestBody(input2)
33318
+ });
33319
+ if (response.status !== 201) {
33320
+ throw toApiError3(response.status, response.body);
33321
+ }
33322
+ return response.body;
33323
+ },
33324
+ async updateHealthCheck(input2) {
33325
+ const response = await httpClient.request({
33326
+ method: "PATCH",
33327
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks/${encodeURIComponent(input2.checkId)}`,
33328
+ bearerToken: input2.bearerToken,
33329
+ body: buildUpdateRequestBody(input2)
33330
+ });
33331
+ if (response.status !== 200) {
33332
+ throw toApiError3(response.status, response.body);
33333
+ }
33334
+ return response.body;
33335
+ },
33336
+ async deleteHealthCheck(input2) {
33337
+ const response = await httpClient.request({
33338
+ method: "DELETE",
33339
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks/${encodeURIComponent(input2.checkId)}`,
33340
+ bearerToken: input2.bearerToken
33341
+ });
33342
+ if (response.status !== 200) {
33343
+ throw toApiError3(response.status, response.body);
33344
+ }
33345
+ return response.body;
33346
+ },
33347
+ async testHealthCheck(input2) {
33348
+ const response = await httpClient.request({
33349
+ method: "POST",
33350
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks/test`,
33351
+ bearerToken: input2.bearerToken,
33352
+ body: {
33353
+ url: input2.url,
33354
+ method: input2.method,
33355
+ expected_status_min: input2.expectedStatusMin,
33356
+ expected_status_max: input2.expectedStatusMax,
33357
+ timeout_ms: input2.timeoutMs
33358
+ }
33359
+ });
33360
+ if (response.status !== 200) {
33361
+ throw toApiError3(response.status, response.body);
33362
+ }
33363
+ return response.body;
33364
+ },
33365
+ async listHealthCheckResults(input2) {
33366
+ const limit = input2.limit ?? 20;
33367
+ const response = await httpClient.request({
33368
+ method: "GET",
33369
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks/${encodeURIComponent(input2.checkId)}/results?limit=${encodeURIComponent(String(limit))}`,
33370
+ bearerToken: input2.bearerToken
33371
+ });
33372
+ if (response.status !== 200) {
33373
+ throw toApiError3(response.status, response.body);
33374
+ }
33375
+ return response.body;
33376
+ },
33377
+ async listHealthCheckDailyRollups(input2) {
33378
+ const limit = input2.limit ?? 30;
33379
+ const response = await httpClient.request({
33380
+ method: "GET",
33381
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks/${encodeURIComponent(input2.checkId)}/daily-rollups?limit=${encodeURIComponent(String(limit))}`,
33382
+ bearerToken: input2.bearerToken
33383
+ });
33384
+ if (response.status !== 200) {
33385
+ throw toApiError3(response.status, response.body);
33386
+ }
33387
+ return response.body;
33388
+ }
33389
+ };
33390
+ }
33391
+ function formatServiceAndEnvironment(check) {
33392
+ return `${check.service_name ?? "availability"}/${check.environment}`;
33393
+ }
33394
+ function formatNullable(value) {
33395
+ return value === null ? "-" : String(value);
33396
+ }
33397
+ function formatCheckSummary(check) {
33398
+ const lastResult = check.last_result_status === null ? "no checks yet" : `${check.last_result_status}${check.last_result_http_status === null ? "" : ` ${check.last_result_http_status}`}`;
33399
+ return [
33400
+ `${check.check_id} ${check.name} [${check.status}]`,
33401
+ `${check.method} ${check.url}`,
33402
+ `interval=${check.interval_seconds}s timeout=${check.timeout_ms}ms expected=${check.expected_status_min}-${check.expected_status_max}`,
33403
+ `service=${formatServiceAndEnvironment(check)} enabled=${check.enabled ? "true" : "false"} last=${lastResult}`
33404
+ ].join("\n");
33405
+ }
33406
+ function formatCheckResultSummary(result) {
33407
+ return [
33408
+ `${result.started_at} ${result.status}`,
33409
+ `http=${formatNullable(result.http_status)} duration=${result.duration_ms}ms redirects=${result.redirect_count}`,
33410
+ `host=${result.checked_url_host} final=${result.final_url}`
33411
+ ].join(" ");
33412
+ }
33413
+ function formatCheckDailyRollupSummary(rollup) {
33414
+ return [
33415
+ `${rollup.day} ${rollup.state}`,
33416
+ `checks=${rollup.total_checks}`,
33417
+ `success=${rollup.successful_checks}`,
33418
+ `failed=${rollup.failed_checks}`,
33419
+ `degraded=${rollup.degraded_checks}`,
33420
+ `avg=${formatNullable(rollup.avg_duration_ms)}ms`,
33421
+ `downtime=${rollup.downtime_seconds}s`
33422
+ ].join(" ");
33423
+ }
33424
+ function formatTestResult(result) {
33425
+ return [
33426
+ `Test result: ${result.result.status}`,
33427
+ `http=${formatNullable(result.result.http_status)}`,
33428
+ `duration=${result.result.duration_ms}ms`,
33429
+ `host=${result.result.checked_url_host}`,
33430
+ `final=${result.result.final_url}`
33431
+ ].join(" ");
33432
+ }
33433
+ async function listHealthChecksCommand(input2, api) {
33434
+ try {
33435
+ const result = await api.listHealthChecks({
33436
+ bearerToken: input2.bearerToken,
33437
+ projectId: input2.projectId,
33438
+ ...input2.limit === void 0 ? {} : { limit: input2.limit }
33439
+ });
33440
+ if (input2.json) {
33441
+ return { exitCode: 0, output: JSON.stringify(result) };
33442
+ }
33443
+ if (result.checks.length === 0) {
33444
+ return {
33445
+ exitCode: 0,
33446
+ output: `No health checks.
33447
+ Plan limits: ${result.limits.max_checks_per_project} checks, minimum interval ${result.limits.min_interval_seconds}s.`
33448
+ };
33449
+ }
33450
+ return {
33451
+ exitCode: 0,
33452
+ output: result.checks.map(formatCheckSummary).join("\n\n")
33453
+ };
33454
+ } catch (error) {
33455
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33456
+ }
33457
+ }
33458
+ async function getHealthCheckCommand(input2, api) {
33459
+ try {
33460
+ const result = await api.getHealthCheck({
33461
+ bearerToken: input2.bearerToken,
33462
+ projectId: input2.projectId,
33463
+ checkId: input2.checkId
33464
+ });
33465
+ if (input2.json) {
33466
+ return { exitCode: 0, output: JSON.stringify(result) };
33467
+ }
33468
+ return {
33469
+ exitCode: 0,
33470
+ output: `${formatCheckSummary(result.check)}
33471
+ limits=${result.limits.max_checks_per_project} min_interval=${result.limits.min_interval_seconds}s`
33472
+ };
33473
+ } catch (error) {
33474
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33475
+ }
33476
+ }
33477
+ async function createHealthCheckCommand(input2, api) {
33478
+ try {
33479
+ const result = await api.createHealthCheck(input2);
33480
+ if (input2.json) {
33481
+ return { exitCode: 0, output: JSON.stringify(result) };
33482
+ }
33483
+ return {
33484
+ exitCode: 0,
33485
+ output: `Health check created: ${result.check.check_id} (${result.check.name})`
33486
+ };
33487
+ } catch (error) {
33488
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33489
+ }
33490
+ }
33491
+ async function updateHealthCheckCommand(input2, api) {
33492
+ try {
33493
+ const result = await api.updateHealthCheck(input2);
33494
+ if (input2.json) {
33495
+ return { exitCode: 0, output: JSON.stringify(result) };
33496
+ }
33497
+ return {
33498
+ exitCode: 0,
33499
+ output: `Health check updated: ${result.check.check_id} (${result.check.name})`
33500
+ };
33501
+ } catch (error) {
33502
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33503
+ }
33504
+ }
33505
+ async function deleteHealthCheckCommand(input2, api) {
33506
+ try {
33507
+ const result = await api.deleteHealthCheck({
33508
+ bearerToken: input2.bearerToken,
33509
+ projectId: input2.projectId,
33510
+ checkId: input2.checkId
33511
+ });
33512
+ if (input2.json) {
33513
+ return { exitCode: 0, output: JSON.stringify(result) };
33514
+ }
33515
+ return {
33516
+ exitCode: 0,
33517
+ output: result.deleted ? "Health check deleted." : "Health check was already deleted."
33518
+ };
33519
+ } catch (error) {
33520
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33521
+ }
33522
+ }
33523
+ async function testHealthCheckCommand(input2, api) {
33524
+ try {
33525
+ const result = await api.testHealthCheck(input2);
33526
+ if (input2.json) {
33527
+ return { exitCode: 0, output: JSON.stringify(result) };
33528
+ }
33529
+ return {
33530
+ exitCode: 0,
33531
+ output: formatTestResult(result)
33532
+ };
33533
+ } catch (error) {
33534
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33535
+ }
33536
+ }
33537
+ async function listHealthCheckResultsCommand(input2, api) {
33538
+ try {
33539
+ const result = await api.listHealthCheckResults({
33540
+ bearerToken: input2.bearerToken,
33541
+ projectId: input2.projectId,
33542
+ checkId: input2.checkId,
33543
+ ...input2.limit === void 0 ? {} : { limit: input2.limit }
33544
+ });
33545
+ if (input2.json) {
33546
+ return { exitCode: 0, output: JSON.stringify(result) };
33547
+ }
33548
+ if (result.results.length === 0) {
33549
+ return { exitCode: 0, output: "No health check results." };
33550
+ }
33551
+ return {
33552
+ exitCode: 0,
33553
+ output: result.results.map(formatCheckResultSummary).join("\n")
33554
+ };
33555
+ } catch (error) {
33556
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33557
+ }
33558
+ }
33559
+ async function listHealthCheckDailyRollupsCommand(input2, api) {
33560
+ try {
33561
+ const result = await api.listHealthCheckDailyRollups({
33562
+ bearerToken: input2.bearerToken,
33563
+ projectId: input2.projectId,
33564
+ checkId: input2.checkId,
33565
+ ...input2.limit === void 0 ? {} : { limit: input2.limit }
33566
+ });
33567
+ if (input2.json) {
33568
+ return { exitCode: 0, output: JSON.stringify(result) };
33569
+ }
33570
+ if (result.rollups.length === 0) {
33571
+ return { exitCode: 0, output: "No health check daily rollups." };
33572
+ }
33573
+ return {
33574
+ exitCode: 0,
33575
+ output: result.rollups.map(formatCheckDailyRollupSummary).join("\n")
33576
+ };
33577
+ } catch (error) {
33578
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33579
+ }
33580
+ }
33581
+ async function createAuthenticatedHealthCheckApi(input2, dependencies) {
33582
+ const readAuth = dependencies?.readAuthState ?? readCliAuthState;
33583
+ const authStateInput = {};
33584
+ if (input2.authFilePath !== void 0) {
33585
+ authStateInput.authFilePath = input2.authFilePath;
33586
+ }
33587
+ const authState = await readAuth(authStateInput);
33588
+ const createHttpClient = dependencies?.createHttpClient ?? ((clientInput) => createCliHttpClient(clientInput));
33589
+ const httpClient = createHttpClient({ baseUrl: authState.base_url });
33590
+ const createApi = dependencies?.createApi ?? createHealthCheckApi;
33591
+ return { authState, api: createApi(httpClient) };
33592
+ }
33593
+ async function listHealthChecksWithAuthCommand(input2, dependencies) {
33594
+ return runAuthenticatedCliCommand(input2, {
33595
+ createApi: createAuthenticatedHealthCheckApi,
33596
+ dependencies,
33597
+ runCommand: (authState, api) => listHealthChecksCommand(
33598
+ {
33599
+ bearerToken: authState.bearer_token,
33600
+ projectId: input2.projectId,
33601
+ ...input2.limit === void 0 ? {} : { limit: input2.limit },
33602
+ ...input2.json === void 0 ? {} : { json: input2.json }
33603
+ },
33604
+ { listHealthChecks: (requestInput) => api.listHealthChecks(requestInput) }
33605
+ )
33606
+ });
33607
+ }
33608
+ async function getHealthCheckWithAuthCommand(input2, dependencies) {
33609
+ return runAuthenticatedCliCommand(input2, {
33610
+ createApi: createAuthenticatedHealthCheckApi,
33611
+ dependencies,
33612
+ runCommand: (authState, api) => getHealthCheckCommand(
33613
+ {
33614
+ bearerToken: authState.bearer_token,
33615
+ projectId: input2.projectId,
33616
+ checkId: input2.checkId,
33617
+ ...input2.json === void 0 ? {} : { json: input2.json }
33618
+ },
33619
+ { getHealthCheck: (requestInput) => api.getHealthCheck(requestInput) }
33620
+ )
33621
+ });
33622
+ }
33623
+ async function createHealthCheckWithAuthCommand(input2, dependencies) {
33624
+ return runAuthenticatedCliCommand(input2, {
33625
+ createApi: createAuthenticatedHealthCheckApi,
33626
+ dependencies,
33627
+ runCommand: (authState, api) => {
33628
+ const commandInput = {
33629
+ ...input2,
33630
+ bearerToken: authState.bearer_token
33631
+ };
33632
+ return createHealthCheckCommand(commandInput, {
33633
+ createHealthCheck: (requestInput) => api.createHealthCheck(requestInput)
33634
+ });
33635
+ }
33636
+ });
33637
+ }
33638
+ async function updateHealthCheckWithAuthCommand(input2, dependencies) {
33639
+ return runAuthenticatedCliCommand(input2, {
33640
+ createApi: createAuthenticatedHealthCheckApi,
33641
+ dependencies,
33642
+ runCommand: (authState, api) => {
33643
+ const commandInput = {
33644
+ ...input2,
33645
+ bearerToken: authState.bearer_token
33646
+ };
33647
+ return updateHealthCheckCommand(commandInput, {
33648
+ updateHealthCheck: (requestInput) => api.updateHealthCheck(requestInput)
33649
+ });
33650
+ }
33651
+ });
33652
+ }
33653
+ async function deleteHealthCheckWithAuthCommand(input2, dependencies) {
33654
+ return runAuthenticatedCliCommand(input2, {
33655
+ createApi: createAuthenticatedHealthCheckApi,
33656
+ dependencies,
33657
+ runCommand: (authState, api) => deleteHealthCheckCommand(
33658
+ {
33659
+ bearerToken: authState.bearer_token,
33660
+ projectId: input2.projectId,
33661
+ checkId: input2.checkId,
33662
+ ...input2.json === void 0 ? {} : { json: input2.json }
33663
+ },
33664
+ { deleteHealthCheck: (requestInput) => api.deleteHealthCheck(requestInput) }
33665
+ )
33666
+ });
33667
+ }
33668
+ async function testHealthCheckWithAuthCommand(input2, dependencies) {
33669
+ return runAuthenticatedCliCommand(input2, {
33670
+ createApi: createAuthenticatedHealthCheckApi,
33671
+ dependencies,
33672
+ runCommand: (authState, api) => {
33673
+ const commandInput = {
33674
+ ...input2,
33675
+ bearerToken: authState.bearer_token
33676
+ };
33677
+ return testHealthCheckCommand(commandInput, {
33678
+ testHealthCheck: (requestInput) => api.testHealthCheck(requestInput)
33679
+ });
33680
+ }
33681
+ });
33682
+ }
33683
+ async function listHealthCheckResultsWithAuthCommand(input2, dependencies) {
33684
+ return runAuthenticatedCliCommand(input2, {
33685
+ createApi: createAuthenticatedHealthCheckApi,
33686
+ dependencies,
33687
+ runCommand: (authState, api) => listHealthCheckResultsCommand(
33688
+ {
33689
+ bearerToken: authState.bearer_token,
33690
+ projectId: input2.projectId,
33691
+ checkId: input2.checkId,
33692
+ ...input2.limit === void 0 ? {} : { limit: input2.limit },
33693
+ ...input2.json === void 0 ? {} : { json: input2.json }
33694
+ },
33695
+ { listHealthCheckResults: (requestInput) => api.listHealthCheckResults(requestInput) }
33696
+ )
33697
+ });
33698
+ }
33699
+ async function listHealthCheckDailyRollupsWithAuthCommand(input2, dependencies) {
33700
+ return runAuthenticatedCliCommand(input2, {
33701
+ createApi: createAuthenticatedHealthCheckApi,
33702
+ dependencies,
33703
+ runCommand: (authState, api) => listHealthCheckDailyRollupsCommand(
33704
+ {
33705
+ bearerToken: authState.bearer_token,
33706
+ projectId: input2.projectId,
33707
+ checkId: input2.checkId,
33708
+ ...input2.limit === void 0 ? {} : { limit: input2.limit },
33709
+ ...input2.json === void 0 ? {} : { json: input2.json }
33710
+ },
33711
+ { listHealthCheckDailyRollups: (requestInput) => api.listHealthCheckDailyRollups(requestInput) }
33712
+ )
33713
+ });
33714
+ }
33715
+
33716
+ // src/management-health-command-handlers.ts
33717
+ function readOptionalServiceName(parsedArgv) {
33718
+ const service = readStringOption(parsedArgv, "service");
33719
+ if (service === void 0) {
33720
+ return void 0;
33721
+ }
33722
+ return service === "null" ? null : service;
33723
+ }
33724
+ function readRequiredProjectId(parsedArgv) {
33725
+ const projectId = readStringOption(parsedArgv, "project-id");
33726
+ if (projectId === void 0) {
33727
+ throw new CliInputError("Missing required option --project-id.");
33728
+ }
33729
+ return projectId;
33730
+ }
33731
+ function readRequiredUrl(parsedArgv) {
33732
+ const url = readStringOption(parsedArgv, "url");
33733
+ if (url === void 0) {
33734
+ throw new CliInputError("Missing required option --url.");
33735
+ }
33736
+ return url;
33737
+ }
33738
+ function readRequiredName(parsedArgv) {
33739
+ const name = readStringOption(parsedArgv, "name");
33740
+ if (name === void 0) {
33741
+ throw new CliInputError("Missing required option --name.");
33742
+ }
33743
+ return name;
33744
+ }
33745
+ async function handleHealthCommand(parsedArgv, dependencies) {
33746
+ const resource = requirePositional(parsedArgv, 1, "resource");
33747
+ if (resource !== "checks") {
33748
+ throw new CliInputError("Unknown health command.");
33749
+ }
33750
+ const action = requirePositional(parsedArgv, 2, "action");
33751
+ if (action === "list") {
33752
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id", "limit"]);
33753
+ ensureNoExtraPositionals(parsedArgv, 3);
33754
+ const limit = readLimitOption(parsedArgv);
33755
+ return await (dependencies.listHealthChecksCommand ?? listHealthChecksWithAuthCommand)(
33756
+ appendCommonAuthOptions(parsedArgv, {
33757
+ projectId: readRequiredProjectId(parsedArgv),
33758
+ ...limit === void 0 ? {} : { limit }
33759
+ })
33760
+ );
33761
+ }
33762
+ if (action === "get") {
33763
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id"]);
33764
+ ensureNoExtraPositionals(parsedArgv, 4);
33765
+ return await (dependencies.getHealthCheckCommand ?? getHealthCheckWithAuthCommand)(
33766
+ appendCommonAuthOptions(parsedArgv, {
33767
+ projectId: readRequiredProjectId(parsedArgv),
33768
+ checkId: requirePositional(parsedArgv, 3, "check-id")
33769
+ })
33770
+ );
33771
+ }
33772
+ if (action === "create") {
33773
+ expectNoUnknownOptions(parsedArgv, [
33774
+ "auth-file",
33775
+ "json",
33776
+ "project-id",
33777
+ "name",
33778
+ "url",
33779
+ "method",
33780
+ "expected-status-min",
33781
+ "expected-status-max",
33782
+ "timeout-ms",
33783
+ "interval-seconds",
33784
+ "failure-threshold",
33785
+ "recovery-threshold",
33786
+ "environment",
33787
+ "service",
33788
+ "enabled"
33789
+ ]);
33790
+ ensureNoExtraPositionals(parsedArgv, 3);
33791
+ const intervalSeconds = readIntegerOption(parsedArgv, "interval-seconds");
33792
+ if (intervalSeconds === void 0) {
33793
+ throw new CliInputError("Missing required option --interval-seconds.");
33794
+ }
33795
+ const method = readStringOption(parsedArgv, "method") ?? "GET";
33796
+ if (method !== "GET" && method !== "HEAD") {
33797
+ throw new CliInputError("Invalid value for --method.");
33798
+ }
33799
+ const enabled = readBooleanStringOption(parsedArgv, "enabled") ?? true;
33800
+ const environment = readStringOption(parsedArgv, "environment");
33801
+ const serviceName = readOptionalServiceName(parsedArgv);
33802
+ return await (dependencies.createHealthCheckCommand ?? createHealthCheckWithAuthCommand)(
33803
+ appendCommonAuthOptions(parsedArgv, {
33804
+ projectId: readRequiredProjectId(parsedArgv),
33805
+ name: readRequiredName(parsedArgv),
33806
+ url: readRequiredUrl(parsedArgv),
33807
+ method,
33808
+ expectedStatusMin: readIntegerOption(parsedArgv, "expected-status-min") ?? 200,
33809
+ expectedStatusMax: readIntegerOption(parsedArgv, "expected-status-max") ?? 399,
33810
+ timeoutMs: readIntegerOption(parsedArgv, "timeout-ms") ?? 5e3,
33811
+ intervalSeconds,
33812
+ failureThreshold: readIntegerOption(parsedArgv, "failure-threshold") ?? 3,
33813
+ recoveryThreshold: readIntegerOption(parsedArgv, "recovery-threshold") ?? 2,
33814
+ ...environment === void 0 ? {} : { environment },
33815
+ ...serviceName === void 0 ? {} : { serviceName },
33816
+ enabled
33817
+ })
33818
+ );
33819
+ }
33820
+ if (action === "update") {
33821
+ expectNoUnknownOptions(parsedArgv, [
33822
+ "auth-file",
33823
+ "json",
33824
+ "project-id",
33825
+ "name",
33826
+ "url",
33827
+ "method",
33828
+ "expected-status-min",
33829
+ "expected-status-max",
33830
+ "timeout-ms",
33831
+ "interval-seconds",
33832
+ "failure-threshold",
33833
+ "recovery-threshold",
33834
+ "environment",
33835
+ "service",
33836
+ "enabled"
33837
+ ]);
33838
+ ensureNoExtraPositionals(parsedArgv, 4);
33839
+ const method = readStringOption(parsedArgv, "method");
33840
+ if (method !== void 0 && method !== "GET" && method !== "HEAD") {
33841
+ throw new CliInputError("Invalid value for --method.");
33842
+ }
33843
+ const input2 = appendCommonAuthOptions(parsedArgv, {
33844
+ projectId: readRequiredProjectId(parsedArgv),
33845
+ checkId: requirePositional(parsedArgv, 3, "check-id")
33846
+ });
33847
+ const name = readStringOption(parsedArgv, "name");
33848
+ const url = readStringOption(parsedArgv, "url");
33849
+ const expectedStatusMin = readIntegerOption(parsedArgv, "expected-status-min");
33850
+ const expectedStatusMax = readIntegerOption(parsedArgv, "expected-status-max");
33851
+ const timeoutMs = readIntegerOption(parsedArgv, "timeout-ms");
33852
+ const intervalSeconds = readIntegerOption(parsedArgv, "interval-seconds");
33853
+ const failureThreshold = readIntegerOption(parsedArgv, "failure-threshold");
33854
+ const recoveryThreshold = readIntegerOption(parsedArgv, "recovery-threshold");
33855
+ const environment = readStringOption(parsedArgv, "environment");
33856
+ const serviceName = readOptionalServiceName(parsedArgv);
33857
+ const enabled = readBooleanStringOption(parsedArgv, "enabled");
33858
+ if (name !== void 0) input2.name = name;
33859
+ if (url !== void 0) input2.url = url;
33860
+ if (method !== void 0) input2.method = method;
33861
+ if (expectedStatusMin !== void 0) input2.expectedStatusMin = expectedStatusMin;
33862
+ if (expectedStatusMax !== void 0) input2.expectedStatusMax = expectedStatusMax;
33863
+ if (timeoutMs !== void 0) input2.timeoutMs = timeoutMs;
33864
+ if (intervalSeconds !== void 0) input2.intervalSeconds = intervalSeconds;
33865
+ if (failureThreshold !== void 0) input2.failureThreshold = failureThreshold;
33866
+ if (recoveryThreshold !== void 0) input2.recoveryThreshold = recoveryThreshold;
33867
+ if (environment !== void 0) input2.environment = environment;
33868
+ if (serviceName !== void 0) input2.serviceName = serviceName;
33869
+ if (enabled !== void 0) input2.enabled = enabled;
33870
+ const hasChanges = name !== void 0 || url !== void 0 || method !== void 0 || expectedStatusMin !== void 0 || expectedStatusMax !== void 0 || timeoutMs !== void 0 || intervalSeconds !== void 0 || failureThreshold !== void 0 || recoveryThreshold !== void 0 || environment !== void 0 || serviceName !== void 0 || enabled !== void 0;
33871
+ if (!hasChanges) {
33872
+ throw new CliInputError("At least one health-check field must be provided.");
33873
+ }
33874
+ return await (dependencies.updateHealthCheckCommand ?? updateHealthCheckWithAuthCommand)(input2);
33875
+ }
33876
+ if (action === "delete") {
33877
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id"]);
33878
+ ensureNoExtraPositionals(parsedArgv, 4);
33879
+ return await (dependencies.deleteHealthCheckCommand ?? deleteHealthCheckWithAuthCommand)(
33880
+ appendCommonAuthOptions(parsedArgv, {
33881
+ projectId: readRequiredProjectId(parsedArgv),
33882
+ checkId: requirePositional(parsedArgv, 3, "check-id")
33883
+ })
33884
+ );
33885
+ }
33886
+ if (action === "test") {
33887
+ expectNoUnknownOptions(parsedArgv, [
33888
+ "auth-file",
33889
+ "json",
33890
+ "project-id",
33891
+ "url",
33892
+ "method",
33893
+ "expected-status-min",
33894
+ "expected-status-max",
33895
+ "timeout-ms"
33896
+ ]);
33897
+ ensureNoExtraPositionals(parsedArgv, 3);
33898
+ const method = readStringOption(parsedArgv, "method") ?? "GET";
33899
+ if (method !== "GET" && method !== "HEAD") {
33900
+ throw new CliInputError("Invalid value for --method.");
33901
+ }
33902
+ return await (dependencies.testHealthCheckCommand ?? testHealthCheckWithAuthCommand)(
33903
+ appendCommonAuthOptions(parsedArgv, {
33904
+ projectId: readRequiredProjectId(parsedArgv),
33905
+ url: readRequiredUrl(parsedArgv),
33906
+ method,
33907
+ expectedStatusMin: readIntegerOption(parsedArgv, "expected-status-min") ?? 200,
33908
+ expectedStatusMax: readIntegerOption(parsedArgv, "expected-status-max") ?? 399,
33909
+ timeoutMs: readIntegerOption(parsedArgv, "timeout-ms") ?? 5e3
33910
+ })
33911
+ );
33912
+ }
33913
+ if (action === "results") {
33914
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id", "limit"]);
33915
+ ensureNoExtraPositionals(parsedArgv, 4);
33916
+ const limit = readLimitOption(parsedArgv);
33917
+ return await (dependencies.listHealthCheckResultsCommand ?? listHealthCheckResultsWithAuthCommand)(
33918
+ appendCommonAuthOptions(parsedArgv, {
33919
+ projectId: readRequiredProjectId(parsedArgv),
33920
+ checkId: requirePositional(parsedArgv, 3, "check-id"),
33921
+ ...limit === void 0 ? {} : { limit }
33922
+ })
33923
+ );
33924
+ }
33925
+ if (action === "daily-rollups") {
33926
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id", "limit"]);
33927
+ ensureNoExtraPositionals(parsedArgv, 4);
33928
+ const limit = readLimitOption(parsedArgv);
33929
+ return await (dependencies.listHealthCheckDailyRollupsCommand ?? listHealthCheckDailyRollupsWithAuthCommand)(
33930
+ appendCommonAuthOptions(parsedArgv, {
33931
+ projectId: readRequiredProjectId(parsedArgv),
33932
+ checkId: requirePositional(parsedArgv, 3, "check-id"),
33933
+ ...limit === void 0 ? {} : { limit }
33934
+ })
33935
+ );
33936
+ }
33937
+ throw new CliInputError("Unknown health checks command.");
33938
+ }
33939
+
33940
+ // src/capture-policy-commands.ts
33941
+ var CapturePolicyApiError = class extends Error {
33942
+ status;
33943
+ constructor(status, message) {
33944
+ super(message);
33945
+ this.name = "CapturePolicyApiError";
33946
+ this.status = status;
33947
+ }
33948
+ };
33949
+ function toApiError4(status, body, fallback) {
33950
+ if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
33951
+ return new CapturePolicyApiError(status, body.error);
33952
+ }
33953
+ return new CapturePolicyApiError(status, fallback);
33954
+ }
33955
+ function createCapturePolicyApi(httpClient) {
33956
+ return {
33957
+ async getCapturePolicy(input2) {
33958
+ const response = await httpClient.request({
33959
+ method: "GET",
33960
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/capture-policy`,
33961
+ bearerToken: input2.bearerToken
33962
+ });
33963
+ if (response.status !== 200) {
33964
+ throw toApiError4(response.status, response.body, "Failed to get capture policy.");
33965
+ }
33966
+ const parsed = CapturePolicyResponseSchema.safeParse(response.body);
33967
+ if (!parsed.success) {
33968
+ throw new CapturePolicyApiError(500, "Invalid capture policy response.");
33969
+ }
33970
+ return parsed.data;
33971
+ },
33972
+ async updateCapturePolicy(input2) {
33973
+ const response = await httpClient.request({
33974
+ method: "PATCH",
33975
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/capture-policy`,
33976
+ bearerToken: input2.bearerToken,
33977
+ body: input2.update
33978
+ });
33979
+ if (response.status !== 200) {
33980
+ throw toApiError4(response.status, response.body, "Failed to update capture policy.");
33981
+ }
33982
+ const parsed = CapturePolicyResponseSchema.safeParse(response.body);
33983
+ if (!parsed.success) {
32568
33984
  throw new CapturePolicyApiError(500, "Invalid capture policy response.");
32569
33985
  }
32570
33986
  return parsed.data;
32571
33987
  }
32572
33988
  };
32573
33989
  }
32574
- function mapErrorToExitCode11(error) {
33990
+ function mapErrorToExitCode12(error) {
32575
33991
  if (!(error instanceof CapturePolicyApiError)) {
32576
33992
  return 1;
32577
33993
  }
@@ -32644,7 +34060,7 @@ async function getCapturePolicyCommand(input2, api) {
32644
34060
  };
32645
34061
  } catch (error) {
32646
34062
  return {
32647
- exitCode: mapErrorToExitCode11(error),
34063
+ exitCode: mapErrorToExitCode12(error),
32648
34064
  output: error instanceof Error ? error.message : String(error)
32649
34065
  };
32650
34066
  }
@@ -32670,7 +34086,7 @@ ${formatPolicy(response)}`
32670
34086
  };
32671
34087
  } catch (error) {
32672
34088
  return {
32673
- exitCode: mapErrorToExitCode11(error),
34089
+ exitCode: mapErrorToExitCode12(error),
32674
34090
  output: error instanceof Error ? error.message : String(error)
32675
34091
  };
32676
34092
  }
@@ -32743,7 +34159,7 @@ var CaptureRuleApiError = class extends Error {
32743
34159
  this.status = status;
32744
34160
  }
32745
34161
  };
32746
- function toApiError4(status, body, fallback) {
34162
+ function toApiError5(status, body, fallback) {
32747
34163
  if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
32748
34164
  return new CaptureRuleApiError(status, body.error);
32749
34165
  }
@@ -32758,7 +34174,7 @@ function createCaptureRuleApi(httpClient) {
32758
34174
  bearerToken: input2.bearerToken
32759
34175
  });
32760
34176
  if (response.status !== 200) {
32761
- throw toApiError4(response.status, response.body, "Failed to list capture rules.");
34177
+ throw toApiError5(response.status, response.body, "Failed to list capture rules.");
32762
34178
  }
32763
34179
  const parsed = CaptureRulesResponseSchema.safeParse(response.body);
32764
34180
  if (!parsed.success) {
@@ -32774,7 +34190,7 @@ function createCaptureRuleApi(httpClient) {
32774
34190
  body: input2.create
32775
34191
  });
32776
34192
  if (response.status !== 201) {
32777
- throw toApiError4(response.status, response.body, "Failed to create capture rule.");
34193
+ throw toApiError5(response.status, response.body, "Failed to create capture rule.");
32778
34194
  }
32779
34195
  const parsed = CaptureRuleResponseSchema.safeParse(response.body);
32780
34196
  if (!parsed.success) {
@@ -32789,7 +34205,7 @@ function createCaptureRuleApi(httpClient) {
32789
34205
  bearerToken: input2.bearerToken
32790
34206
  });
32791
34207
  if (response.status !== 200) {
32792
- throw toApiError4(response.status, response.body, "Failed to suggest capture rules.");
34208
+ throw toApiError5(response.status, response.body, "Failed to suggest capture rules.");
32793
34209
  }
32794
34210
  const parsed = CaptureRuleSuggestionsResponseSchema.safeParse(response.body);
32795
34211
  if (!parsed.success) {
@@ -32805,7 +34221,7 @@ function createCaptureRuleApi(httpClient) {
32805
34221
  body: input2.create
32806
34222
  });
32807
34223
  if (response.status !== 201) {
32808
- throw toApiError4(response.status, response.body, "Failed to create capture rule from suggestion.");
34224
+ throw toApiError5(response.status, response.body, "Failed to create capture rule from suggestion.");
32809
34225
  }
32810
34226
  const parsed = CaptureRuleResponseSchema.safeParse(response.body);
32811
34227
  if (!parsed.success) {
@@ -32821,7 +34237,7 @@ function createCaptureRuleApi(httpClient) {
32821
34237
  body: input2.update
32822
34238
  });
32823
34239
  if (response.status !== 200) {
32824
- throw toApiError4(response.status, response.body, "Failed to update capture rule.");
34240
+ throw toApiError5(response.status, response.body, "Failed to update capture rule.");
32825
34241
  }
32826
34242
  const parsed = CaptureRuleResponseSchema.safeParse(response.body);
32827
34243
  if (!parsed.success) {
@@ -32836,7 +34252,7 @@ function createCaptureRuleApi(httpClient) {
32836
34252
  bearerToken: input2.bearerToken
32837
34253
  });
32838
34254
  if (response.status !== 200) {
32839
- throw toApiError4(response.status, response.body, "Failed to delete capture rule.");
34255
+ throw toApiError5(response.status, response.body, "Failed to delete capture rule.");
32840
34256
  }
32841
34257
  if (typeof response.body !== "object" || response.body === null || !("success" in response.body) || response.body.success !== true) {
32842
34258
  throw new CaptureRuleApiError(500, "Invalid capture rule delete response.");
@@ -32845,7 +34261,7 @@ function createCaptureRuleApi(httpClient) {
32845
34261
  }
32846
34262
  };
32847
34263
  }
32848
- function mapErrorToExitCode12(error) {
34264
+ function mapErrorToExitCode13(error) {
32849
34265
  if (!(error instanceof CaptureRuleApiError)) {
32850
34266
  return 1;
32851
34267
  }
@@ -32969,7 +34385,7 @@ async function listCaptureRulesCommand(input2, api) {
32969
34385
  };
32970
34386
  } catch (error) {
32971
34387
  return {
32972
- exitCode: mapErrorToExitCode12(error),
34388
+ exitCode: mapErrorToExitCode13(error),
32973
34389
  output: error instanceof Error ? error.message : String(error)
32974
34390
  };
32975
34391
  }
@@ -32995,7 +34411,7 @@ ${formatRule(response.rule)}`
32995
34411
  };
32996
34412
  } catch (error) {
32997
34413
  return {
32998
- exitCode: mapErrorToExitCode12(error),
34414
+ exitCode: mapErrorToExitCode13(error),
32999
34415
  output: error instanceof Error ? error.message : String(error)
33000
34416
  };
33001
34417
  }
@@ -33012,7 +34428,7 @@ async function suggestCaptureRulesFromIncidentCommand(input2, api) {
33012
34428
  };
33013
34429
  } catch (error) {
33014
34430
  return {
33015
- exitCode: mapErrorToExitCode12(error),
34431
+ exitCode: mapErrorToExitCode13(error),
33016
34432
  output: error instanceof Error ? error.message : String(error)
33017
34433
  };
33018
34434
  }
@@ -33038,7 +34454,7 @@ ${formatRule(response.rule)}`
33038
34454
  };
33039
34455
  } catch (error) {
33040
34456
  return {
33041
- exitCode: mapErrorToExitCode12(error),
34457
+ exitCode: mapErrorToExitCode13(error),
33042
34458
  output: error instanceof Error ? error.message : String(error)
33043
34459
  };
33044
34460
  }
@@ -33065,7 +34481,7 @@ ${formatRule(response.rule)}`
33065
34481
  };
33066
34482
  } catch (error) {
33067
34483
  return {
33068
- exitCode: mapErrorToExitCode12(error),
34484
+ exitCode: mapErrorToExitCode13(error),
33069
34485
  output: error instanceof Error ? error.message : String(error)
33070
34486
  };
33071
34487
  }
@@ -33083,7 +34499,7 @@ async function deleteCaptureRuleCommand(input2, api) {
33083
34499
  };
33084
34500
  } catch (error) {
33085
34501
  return {
33086
- exitCode: mapErrorToExitCode12(error),
34502
+ exitCode: mapErrorToExitCode13(error),
33087
34503
  output: error instanceof Error ? error.message : String(error)
33088
34504
  };
33089
34505
  }
@@ -33210,7 +34626,7 @@ var ProbeApiError = class extends Error {
33210
34626
  this.code = code;
33211
34627
  }
33212
34628
  };
33213
- function toApiError5(status, body) {
34629
+ function toApiError6(status, body) {
33214
34630
  if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
33215
34631
  return new ProbeApiError(status, body.error);
33216
34632
  }
@@ -33241,7 +34657,7 @@ function createProbeApi(httpClient) {
33241
34657
  body
33242
34658
  });
33243
34659
  if (response.status !== 201) {
33244
- throw toApiError5(response.status, response.body);
34660
+ throw toApiError6(response.status, response.body);
33245
34661
  }
33246
34662
  return response.body;
33247
34663
  },
@@ -33252,7 +34668,7 @@ function createProbeApi(httpClient) {
33252
34668
  bearerToken: input2.bearerToken
33253
34669
  });
33254
34670
  if (response.status !== 200) {
33255
- throw toApiError5(response.status, response.body);
34671
+ throw toApiError6(response.status, response.body);
33256
34672
  }
33257
34673
  return response.body;
33258
34674
  },
@@ -33264,13 +34680,13 @@ function createProbeApi(httpClient) {
33264
34680
  body: { activation_id: input2.activationId }
33265
34681
  });
33266
34682
  if (response.status !== 200) {
33267
- throw toApiError5(response.status, response.body);
34683
+ throw toApiError6(response.status, response.body);
33268
34684
  }
33269
34685
  return response.body;
33270
34686
  }
33271
34687
  };
33272
34688
  }
33273
- function mapErrorToExitCode13(error) {
34689
+ function mapErrorToExitCode14(error) {
33274
34690
  if (!(error instanceof ProbeApiError)) {
33275
34691
  return 1;
33276
34692
  }
@@ -33323,7 +34739,7 @@ async function activateProbeCommand(input2, api) {
33323
34739
  Trigger token: ${result.trigger_token}`
33324
34740
  };
33325
34741
  } catch (error) {
33326
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
34742
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
33327
34743
  }
33328
34744
  }
33329
34745
  async function listActiveProbesCommand(input2, api) {
@@ -33343,7 +34759,7 @@ async function listActiveProbesCommand(input2, api) {
33343
34759
  output: result.activations.map((a) => `${a.activation_id} ${a.label_pattern} (${a.service}/${a.environment}) expires ${a.expires_at}`).join("\n")
33344
34760
  };
33345
34761
  } catch (error) {
33346
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
34762
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
33347
34763
  }
33348
34764
  }
33349
34765
  async function deactivateProbeCommand(input2, api) {
@@ -33361,7 +34777,7 @@ async function deactivateProbeCommand(input2, api) {
33361
34777
  output: result.deactivated ? "Probe deactivated." : "Probe was already inactive."
33362
34778
  };
33363
34779
  } catch (error) {
33364
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
34780
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
33365
34781
  }
33366
34782
  }
33367
34783
  async function createAuthenticatedProbeApi(input2, dependencies) {
@@ -33796,7 +35212,7 @@ function handleMemberCommand(parsedArgv, dependencies) {
33796
35212
  }
33797
35213
 
33798
35214
  // src/alert-commands.ts
33799
- function mapErrorToExitCode14(error) {
35215
+ function mapErrorToExitCode15(error) {
33800
35216
  if (!(error instanceof AlertApiError)) {
33801
35217
  return 1;
33802
35218
  }
@@ -33834,7 +35250,7 @@ async function listAlertsCommand(input2, api) {
33834
35250
  output: input2.json ? JSON.stringify({ alerts }) : formatAlertTable(alerts)
33835
35251
  };
33836
35252
  } catch (error) {
33837
- return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
35253
+ return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
33838
35254
  }
33839
35255
  }
33840
35256
  async function listAlertsWithAuthCommand(input2, dependencies) {
@@ -33885,7 +35301,7 @@ async function createAlertCommand(input2, api) {
33885
35301
  output: input2.json ? JSON.stringify({ alert }) : `Alert created: ${alert.alert_id}`
33886
35302
  };
33887
35303
  } catch (error) {
33888
- return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
35304
+ return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
33889
35305
  }
33890
35306
  }
33891
35307
  async function createAlertWithAuthCommand(input2, dependencies) {
@@ -33955,7 +35371,7 @@ async function updateAlertCommand(input2, api) {
33955
35371
  output: input2.json ? JSON.stringify({ alert }) : `Alert updated: ${alert.alert_id}`
33956
35372
  };
33957
35373
  } catch (error) {
33958
- return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
35374
+ return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
33959
35375
  }
33960
35376
  }
33961
35377
  async function updateAlertWithAuthCommand(input2, dependencies) {
@@ -34010,7 +35426,7 @@ async function deleteAlertCommand(input2, api) {
34010
35426
  output: input2.json ? JSON.stringify({ alert }) : `Alert deleted: ${alert.alert_id}`
34011
35427
  };
34012
35428
  } catch (error) {
34013
- return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
35429
+ return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
34014
35430
  }
34015
35431
  }
34016
35432
  async function deleteAlertWithAuthCommand(input2, dependencies) {
@@ -34034,7 +35450,7 @@ async function deleteAlertWithAuthCommand(input2, dependencies) {
34034
35450
  }
34035
35451
 
34036
35452
  // src/slack-commands.ts
34037
- function mapErrorToExitCode15(error) {
35453
+ function mapErrorToExitCode16(error) {
34038
35454
  if (!(error instanceof SlackApiError)) {
34039
35455
  return 1;
34040
35456
  }
@@ -34070,7 +35486,7 @@ async function listSlackDestinationsCommand(input2, api) {
34070
35486
  output: input2.json ? JSON.stringify({ destinations }) : formatSlackDestinationTable(destinations)
34071
35487
  };
34072
35488
  } catch (error) {
34073
- return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
35489
+ return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
34074
35490
  }
34075
35491
  }
34076
35492
  async function listSlackDestinationsWithAuthCommand(input2, dependencies) {
@@ -34099,7 +35515,7 @@ async function getSlackConnectUrlCommand(input2, api) {
34099
35515
  output: input2.json ? JSON.stringify({ install_url: installUrl }) : installUrl
34100
35516
  };
34101
35517
  } catch (error) {
34102
- return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
35518
+ return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
34103
35519
  }
34104
35520
  }
34105
35521
  async function getSlackConnectUrlWithAuthCommand(input2, dependencies) {
@@ -34129,7 +35545,7 @@ async function testSlackDestinationCommand(input2, api) {
34129
35545
  output: input2.json ? JSON.stringify({ delivery }) : `Slack test message delivered for destination: ${input2.destinationId}`
34130
35546
  };
34131
35547
  } catch (error) {
34132
- return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
35548
+ return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
34133
35549
  }
34134
35550
  }
34135
35551
  async function testSlackDestinationWithAuthCommand(input2, dependencies) {
@@ -34159,7 +35575,7 @@ async function deleteSlackDestinationCommand(input2, api) {
34159
35575
  output: input2.json ? JSON.stringify({ destination: deleted }) : `Slack destination deleted: ${deleted.slack_destination_id}`
34160
35576
  };
34161
35577
  } catch (error) {
34162
- return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
35578
+ return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
34163
35579
  }
34164
35580
  }
34165
35581
  async function deleteSlackDestinationWithAuthCommand(input2, dependencies) {
@@ -34179,7 +35595,7 @@ async function deleteSlackDestinationWithAuthCommand(input2, dependencies) {
34179
35595
  }
34180
35596
 
34181
35597
  // src/webhook-commands.ts
34182
- function mapErrorToExitCode16(error) {
35598
+ function mapErrorToExitCode17(error) {
34183
35599
  if (!(error instanceof WebhookApiError)) {
34184
35600
  return 1;
34185
35601
  }
@@ -34224,7 +35640,7 @@ async function listWebhooksCommand(input2, api) {
34224
35640
  output: input2.json ? JSON.stringify({ webhooks }) : formatWebhookTable(webhooks)
34225
35641
  };
34226
35642
  } catch (error) {
34227
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35643
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
34228
35644
  }
34229
35645
  }
34230
35646
  async function listWebhooksWithAuthCommand(input2, dependencies) {
@@ -34272,7 +35688,7 @@ async function createWebhookCommand(input2, api) {
34272
35688
  Signing secret: ${webhook.signing_secret}`
34273
35689
  };
34274
35690
  } catch (error) {
34275
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35691
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
34276
35692
  }
34277
35693
  }
34278
35694
  async function createWebhookWithAuthCommand(input2, dependencies) {
@@ -34326,7 +35742,7 @@ async function updateWebhookCommand(input2, api) {
34326
35742
  output: input2.json ? JSON.stringify({ webhook }) : `Webhook updated: ${webhook.webhook_id}`
34327
35743
  };
34328
35744
  } catch (error) {
34329
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35745
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
34330
35746
  }
34331
35747
  }
34332
35748
  async function updateWebhookWithAuthCommand(input2, dependencies) {
@@ -34372,7 +35788,7 @@ async function deleteWebhookCommand(input2, api) {
34372
35788
  output: input2.json ? JSON.stringify({ webhook }) : `Webhook deleted: ${webhook.webhook_id}`
34373
35789
  };
34374
35790
  } catch (error) {
34375
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35791
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
34376
35792
  }
34377
35793
  }
34378
35794
  async function deleteWebhookWithAuthCommand(input2, dependencies) {
@@ -34410,7 +35826,7 @@ async function testWebhookCommand(input2, api) {
34410
35826
  output: input2.json ? JSON.stringify({ delivery }) : `Webhook test queued: ${delivery.delivery_id} | ${delivery.event_type} | attempts=${delivery.attempt_count}`
34411
35827
  };
34412
35828
  } catch (error) {
34413
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35829
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
34414
35830
  }
34415
35831
  }
34416
35832
  async function testWebhookWithAuthCommand(input2, dependencies) {
@@ -34451,7 +35867,7 @@ async function listWebhookDeliveriesCommand(input2, api) {
34451
35867
  output: input2.json ? JSON.stringify({ deliveries }) : formatWebhookDeliveriesTable(deliveries)
34452
35868
  };
34453
35869
  } catch (error) {
34454
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35870
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
34455
35871
  }
34456
35872
  }
34457
35873
  async function listWebhookDeliveriesWithAuthCommand(input2, dependencies) {
@@ -34489,7 +35905,7 @@ async function retryWebhookDeliveryCommand(input2, api) {
34489
35905
  output: input2.json ? JSON.stringify(result) : `Delivery retried: ${result.delivery_id} | ${result.event_type}`
34490
35906
  };
34491
35907
  } catch (error) {
34492
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35908
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
34493
35909
  }
34494
35910
  }
34495
35911
  async function retryWebhookDeliveryWithAuthCommand(input2, dependencies) {
@@ -34514,7 +35930,7 @@ async function retryWebhookDeliveryWithAuthCommand(input2, dependencies) {
34514
35930
  }
34515
35931
 
34516
35932
  // src/weekly-report-commands.ts
34517
- function mapErrorToExitCode17(error) {
35933
+ function mapErrorToExitCode18(error) {
34518
35934
  if (!(error instanceof WeeklyReportApiError)) {
34519
35935
  return 1;
34520
35936
  }
@@ -34549,7 +35965,7 @@ async function listWeeklyReportChannelsCommand(input2, api) {
34549
35965
  output: input2.json ? JSON.stringify({ channels }) : formatWeeklyReportChannelTable(channels)
34550
35966
  };
34551
35967
  } catch (error) {
34552
- return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
35968
+ return { exitCode: mapErrorToExitCode18(error), output: error instanceof Error ? error.message : String(error) };
34553
35969
  }
34554
35970
  }
34555
35971
  async function listWeeklyReportChannelsWithAuthCommand(input2, dependencies) {
@@ -34582,7 +35998,7 @@ async function createWeeklyReportChannelCommand(input2, api) {
34582
35998
  output: input2.json ? JSON.stringify({ channel }) : `Weekly report channel created: ${channel.channel_id}`
34583
35999
  };
34584
36000
  } catch (error) {
34585
- return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
36001
+ return { exitCode: mapErrorToExitCode18(error), output: error instanceof Error ? error.message : String(error) };
34586
36002
  }
34587
36003
  }
34588
36004
  async function createWeeklyReportChannelWithAuthCommand(input2, dependencies) {
@@ -34617,7 +36033,7 @@ async function updateWeeklyReportChannelCommand(input2, api) {
34617
36033
  output: input2.json ? JSON.stringify({ channel }) : `Weekly report channel updated: ${channel.channel_id}`
34618
36034
  };
34619
36035
  } catch (error) {
34620
- return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
36036
+ return { exitCode: mapErrorToExitCode18(error), output: error instanceof Error ? error.message : String(error) };
34621
36037
  }
34622
36038
  }
34623
36039
  async function updateWeeklyReportChannelWithAuthCommand(input2, dependencies) {
@@ -34648,7 +36064,7 @@ async function deleteWeeklyReportChannelCommand(input2, api) {
34648
36064
  output: input2.json ? JSON.stringify({ channel: deleted }) : `Weekly report channel deleted: ${deleted.channel_id}`
34649
36065
  };
34650
36066
  } catch (error) {
34651
- return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
36067
+ return { exitCode: mapErrorToExitCode18(error), output: error instanceof Error ? error.message : String(error) };
34652
36068
  }
34653
36069
  }
34654
36070
  async function deleteWeeklyReportChannelWithAuthCommand(input2, dependencies) {
@@ -35258,7 +36674,7 @@ async function handleCaptureRuleCommand2(parsedArgv, dependencies) {
35258
36674
  // package.json
35259
36675
  var package_default = {
35260
36676
  name: "@debugbundle/cli",
35261
- version: "1.4.0",
36677
+ version: "1.5.1",
35262
36678
  private: false,
35263
36679
  description: "Command-line interface for DebugBundle",
35264
36680
  license: "AGPL-3.0-only",
@@ -35736,6 +37152,9 @@ ${formatUsage()}`
35736
37152
  if (command === "probe") {
35737
37153
  return await handleProbeCommand(parsedArgv, dependencies);
35738
37154
  }
37155
+ if (command === "health") {
37156
+ return await handleHealthCommand(parsedArgv, dependencies);
37157
+ }
35739
37158
  if (command === "member") {
35740
37159
  return await handleMemberCommand(parsedArgv, dependencies);
35741
37160
  }