@debugbundle/cli 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/main.cjs +1873 -232
  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",
@@ -16830,6 +16938,9 @@ function createRetrievalApi(client) {
16830
16938
  if (input2.severity !== void 0) {
16831
16939
  query.set("severity", input2.severity);
16832
16940
  }
16941
+ if (input2.firstSeenAfter !== void 0) {
16942
+ query.set("first_seen_after", input2.firstSeenAfter);
16943
+ }
16833
16944
  if (input2.cursor !== void 0) {
16834
16945
  query.set("cursor", input2.cursor);
16835
16946
  }
@@ -17086,6 +17197,88 @@ function createRetrievalApi(client) {
17086
17197
  };
17087
17198
  }
17088
17199
 
17200
+ // ../../packages/storage/src/account-analytics-store.ts
17201
+ var ACCOUNT_METRIC_KEYS = [
17202
+ "account_created",
17203
+ "account_deleted",
17204
+ "project_created",
17205
+ "project_deleted",
17206
+ "raw_events_accepted",
17207
+ "raw_events_rejected",
17208
+ "events_rejected_malformed",
17209
+ "events_rejected_rate_limited",
17210
+ "events_rejected_quota",
17211
+ "events_rejected_capture_policy",
17212
+ "events_rejected_capture_rule",
17213
+ "billable_events_counted",
17214
+ "incident_signal_events_counted",
17215
+ "context_signal_events_counted",
17216
+ "operational_signal_events_counted",
17217
+ "local_verification_events_accepted",
17218
+ "cloud_verification_events_accepted",
17219
+ "incidents_opened",
17220
+ "incidents_resolved",
17221
+ "incidents_reopened",
17222
+ "incidents_regressed",
17223
+ "incident_occurrences",
17224
+ "incident_occurrences_high_severity",
17225
+ "incident_occurrences_critical_severity",
17226
+ "incidents_auto_detected_spiking",
17227
+ "failure_bundles_created",
17228
+ "failure_bundles_updated",
17229
+ "failure_bundle_generations_failed",
17230
+ "improvement_bundles_created",
17231
+ "improvement_bundles_updated",
17232
+ "improvement_bundle_generations_failed",
17233
+ "reproductions_created",
17234
+ "reproductions_failed",
17235
+ "retention_bundle_owners_rotated",
17236
+ "improvements_opened",
17237
+ "improvements_resolved",
17238
+ "improvements_reopened",
17239
+ "improvements_snoozed",
17240
+ "recurring_incident_improvements_opened",
17241
+ "post_deploy_regression_improvements_opened",
17242
+ "slow_request_improvements_opened",
17243
+ "request_failure_improvements_opened",
17244
+ "warning_log_improvements_opened",
17245
+ "alert_deliveries_created",
17246
+ "alert_deliveries_delivered",
17247
+ "alert_deliveries_failed",
17248
+ "alert_email_digests_sent",
17249
+ "operational_emails_sent",
17250
+ "weekly_reports_sent",
17251
+ "weekly_reports_failed",
17252
+ "webhook_deliveries_created",
17253
+ "webhook_deliveries_delivered",
17254
+ "webhook_deliveries_failed",
17255
+ "webhooks_auto_disabled",
17256
+ "github_dispatches_created",
17257
+ "github_dispatches_delivered",
17258
+ "github_dispatches_failed",
17259
+ "github_dispatch_rules_created",
17260
+ "github_dispatch_rules_deleted",
17261
+ "remote_probe_activations_created",
17262
+ "remote_probe_activations_expired",
17263
+ "probe_events_accepted",
17264
+ "capture_rules_created",
17265
+ "capture_rules_deleted",
17266
+ "capture_policy_updates",
17267
+ "trial_started",
17268
+ "trial_converted",
17269
+ "trial_expired",
17270
+ "plan_upgraded",
17271
+ "plan_downgraded",
17272
+ "capacity_units_purchased",
17273
+ "capacity_units_reduced",
17274
+ "allowance_warning_emails_sent",
17275
+ "allowance_limit_emails_sent",
17276
+ "projects_existing_at_account_deletion",
17277
+ "open_incidents_existing_at_account_deletion",
17278
+ "open_improvements_existing_at_account_deletion"
17279
+ ];
17280
+ var AccountMetricKeySchema = external_exports.enum(ACCOUNT_METRIC_KEYS);
17281
+
17089
17282
  // ../../packages/storage/src/incident-context.ts
17090
17283
  function isRecord2(value) {
17091
17284
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -17371,11 +17564,24 @@ function deriveIncidentReasonFromSourceEventTypes(eventTypes) {
17371
17564
  // ../../packages/auth/src/primitives.ts
17372
17565
  var import_argon2 = require("@node-rs/argon2");
17373
17566
 
17567
+ // ../../packages/auth/src/account-deletion-auth.ts
17568
+ var DEFAULT_ACCOUNT_DELETION_CODE_LIFETIME_MS = 1e3 * 60 * 10;
17569
+
17374
17570
  // ../../packages/auth/src/web-session-auth.ts
17375
17571
  var DEFAULT_SESSION_LIFETIME_MS = 1e3 * 60 * 60 * 24 * 7;
17376
17572
  var DEFAULT_EMAIL_AUTH_CODE_LIFETIME_MS = 1e3 * 60 * 10;
17377
17573
  var DEFAULT_GITHUB_OAUTH_STATE_LIFETIME_MS = 1e3 * 60 * 10;
17378
17574
 
17575
+ // ../../packages/storage/src/availability-check-store-helpers.ts
17576
+ var TIER_CAPABILITIES_SQL = {
17577
+ free_limit: getTierCapabilities("free").availability_checks_per_project,
17578
+ solo_limit: getTierCapabilities("solo").availability_checks_per_project,
17579
+ team_limit: getTierCapabilities("team").availability_checks_per_project,
17580
+ free_interval: getTierCapabilities("free").availability_check_min_interval_seconds,
17581
+ solo_interval: getTierCapabilities("solo").availability_check_min_interval_seconds,
17582
+ team_interval: getTierCapabilities("team").availability_check_min_interval_seconds
17583
+ };
17584
+
17379
17585
  // ../../packages/storage/src/auth-rate-limiter.ts
17380
17586
  var import_ioredis = __toESM(require_built3(), 1);
17381
17587
 
@@ -17880,8 +18086,131 @@ function classifyEvent(eventType, logLevel, probeActivationId, payload, captureP
17880
18086
  var import_ioredis4 = __toESM(require_built3(), 1);
17881
18087
  var DEFAULT_PROCESSING_TIMEOUT_MS = 5 * 60 * 1e3;
17882
18088
 
17883
- // ../../packages/storage/src/schema-migrations.ts
17884
- var import_node_crypto2 = require("node:crypto");
18089
+ // ../../packages/storage/src/availability-check-bootstrap-statements.ts
18090
+ var AVAILABILITY_CHECK_BOOTSTRAP_STATEMENTS = [
18091
+ `
18092
+ CREATE TABLE availability_checks (
18093
+ id uuid PRIMARY KEY,
18094
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
18095
+ created_by_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
18096
+ name text NOT NULL,
18097
+ url text NOT NULL,
18098
+ method text NOT NULL CHECK (method IN ('GET', 'HEAD')),
18099
+ expected_status_min integer NOT NULL DEFAULT 200 CHECK (expected_status_min BETWEEN 100 AND 599),
18100
+ expected_status_max integer NOT NULL DEFAULT 399 CHECK (expected_status_max BETWEEN 100 AND 599),
18101
+ timeout_ms integer NOT NULL DEFAULT 5000 CHECK (timeout_ms BETWEEN 500 AND 5000),
18102
+ interval_seconds integer NOT NULL CHECK (interval_seconds >= 30),
18103
+ failure_threshold integer NOT NULL DEFAULT 3 CHECK (failure_threshold BETWEEN 1 AND 10),
18104
+ recovery_threshold integer NOT NULL DEFAULT 2 CHECK (recovery_threshold BETWEEN 1 AND 10),
18105
+ environment text NOT NULL DEFAULT 'production',
18106
+ service_name text,
18107
+ enabled boolean NOT NULL DEFAULT true,
18108
+ status text NOT NULL DEFAULT 'unknown' CHECK (status IN ('unknown', 'passing', 'failing')),
18109
+ consecutive_failures integer NOT NULL DEFAULT 0,
18110
+ consecutive_successes integer NOT NULL DEFAULT 0,
18111
+ linked_incident_id uuid REFERENCES incidents(id) ON DELETE SET NULL,
18112
+ last_checked_at timestamptz,
18113
+ next_check_at timestamptz,
18114
+ claimed_at timestamptz,
18115
+ last_result_status text CHECK (
18116
+ last_result_status IS NULL OR last_result_status IN (
18117
+ 'success',
18118
+ 'http_status_mismatch',
18119
+ 'timeout',
18120
+ 'dns_error',
18121
+ 'tls_error',
18122
+ 'connection_error',
18123
+ 'redirect_blocked',
18124
+ 'security_blocked',
18125
+ 'internal_error'
18126
+ )
18127
+ ),
18128
+ last_result_http_status integer,
18129
+ last_result_error_kind text,
18130
+ last_result_error_message text,
18131
+ last_result_duration_ms integer,
18132
+ deleted_at timestamptz,
18133
+ created_at timestamptz NOT NULL DEFAULT now(),
18134
+ updated_at timestamptz NOT NULL DEFAULT now()
18135
+ )
18136
+ `,
18137
+ `
18138
+ CREATE INDEX availability_checks_project_created_idx
18139
+ ON availability_checks (project_id, created_at DESC)
18140
+ `,
18141
+ `
18142
+ CREATE INDEX availability_checks_due_idx
18143
+ ON availability_checks (next_check_at, project_id)
18144
+ `,
18145
+ `
18146
+ CREATE INDEX availability_checks_claimed_idx
18147
+ ON availability_checks (claimed_at)
18148
+ `,
18149
+ `
18150
+ CREATE TABLE availability_check_results (
18151
+ id uuid PRIMARY KEY,
18152
+ check_id uuid NOT NULL REFERENCES availability_checks(id) ON DELETE CASCADE,
18153
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
18154
+ started_at timestamptz NOT NULL,
18155
+ completed_at timestamptz NOT NULL,
18156
+ duration_ms integer NOT NULL,
18157
+ status text NOT NULL CHECK (
18158
+ status IN (
18159
+ 'success',
18160
+ 'http_status_mismatch',
18161
+ 'timeout',
18162
+ 'dns_error',
18163
+ 'tls_error',
18164
+ 'connection_error',
18165
+ 'redirect_blocked',
18166
+ 'security_blocked',
18167
+ 'internal_error'
18168
+ )
18169
+ ),
18170
+ http_status integer,
18171
+ error_kind text,
18172
+ error_message text,
18173
+ redirect_count integer NOT NULL DEFAULT 0,
18174
+ checked_url_host text NOT NULL,
18175
+ checked_url_path text NOT NULL,
18176
+ final_url text NOT NULL,
18177
+ created_at timestamptz NOT NULL DEFAULT now()
18178
+ )
18179
+ `,
18180
+ `
18181
+ CREATE INDEX availability_check_results_check_started_idx
18182
+ ON availability_check_results (check_id, started_at DESC)
18183
+ `,
18184
+ `
18185
+ CREATE INDEX availability_check_results_project_started_idx
18186
+ ON availability_check_results (project_id, started_at DESC)
18187
+ `,
18188
+ `
18189
+ CREATE TABLE availability_check_daily_rollups (
18190
+ id uuid PRIMARY KEY,
18191
+ check_id uuid NOT NULL REFERENCES availability_checks(id) ON DELETE CASCADE,
18192
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
18193
+ day date NOT NULL,
18194
+ state text NOT NULL CHECK (state IN ('unknown', 'operational', 'degraded', 'down', 'paused')),
18195
+ total_checks integer NOT NULL DEFAULT 0,
18196
+ successful_checks integer NOT NULL DEFAULT 0,
18197
+ failed_checks integer NOT NULL DEFAULT 0,
18198
+ degraded_checks integer NOT NULL DEFAULT 0,
18199
+ avg_duration_ms integer,
18200
+ first_checked_at timestamptz,
18201
+ last_checked_at timestamptz,
18202
+ downtime_seconds integer NOT NULL DEFAULT 0,
18203
+ incident_ids uuid[] NOT NULL DEFAULT '{}'::uuid[],
18204
+ created_at timestamptz NOT NULL DEFAULT now(),
18205
+ updated_at timestamptz NOT NULL DEFAULT now(),
18206
+ UNIQUE (check_id, day)
18207
+ )
18208
+ `,
18209
+ `
18210
+ CREATE INDEX availability_check_daily_rollups_project_day_idx
18211
+ ON availability_check_daily_rollups (project_id, day DESC)
18212
+ `
18213
+ ];
17885
18214
 
17886
18215
  // ../../packages/storage/src/storage-bootstrap-statements.ts
17887
18216
  var STORAGE_BOOTSTRAP_STATEMENTS = [
@@ -18050,6 +18379,7 @@ var STORAGE_BOOTSTRAP_STATEMENTS = [
18050
18379
  user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
18051
18380
  organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
18052
18381
  session_token_hash text UNIQUE NOT NULL,
18382
+ auth_method text CHECK (auth_method IS NULL OR auth_method IN ('email_code', 'github_oauth')),
18053
18383
  created_at timestamptz NOT NULL DEFAULT now(),
18054
18384
  expires_at timestamptz NOT NULL,
18055
18385
  revoked_at timestamptz
@@ -18082,6 +18412,26 @@ var STORAGE_BOOTSTRAP_STATEMENTS = [
18082
18412
  CREATE INDEX email_auth_challenges_code_hash_idx
18083
18413
  ON email_auth_challenges (code_hash)
18084
18414
  `,
18415
+ `
18416
+ CREATE TABLE account_deletion_challenges (
18417
+ id uuid PRIMARY KEY,
18418
+ organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
18419
+ user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
18420
+ email text NOT NULL,
18421
+ code_hash text NOT NULL,
18422
+ created_at timestamptz NOT NULL DEFAULT now(),
18423
+ expires_at timestamptz NOT NULL,
18424
+ used_at timestamptz
18425
+ )
18426
+ `,
18427
+ `
18428
+ CREATE INDEX account_deletion_challenges_scope_idx
18429
+ ON account_deletion_challenges (organization_id, user_id, lower(email), created_at DESC)
18430
+ `,
18431
+ `
18432
+ CREATE INDEX account_deletion_challenges_code_hash_idx
18433
+ ON account_deletion_challenges (code_hash)
18434
+ `,
18085
18435
  `
18086
18436
  CREATE TABLE github_device_authorizations (
18087
18437
  id uuid PRIMARY KEY,
@@ -18792,6 +19142,103 @@ var STORAGE_BOOTSTRAP_STATEMENTS = [
18792
19142
  PRIMARY KEY (organization_id, period_starts_at)
18793
19143
  )
18794
19144
  `,
19145
+ `
19146
+ CREATE TABLE project_usage_counters (
19147
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
19148
+ period_starts_at timestamptz NOT NULL,
19149
+ raw_ingested_events integer NOT NULL DEFAULT 0,
19150
+ updated_at timestamptz NOT NULL DEFAULT now(),
19151
+ PRIMARY KEY (project_id, period_starts_at)
19152
+ )
19153
+ `,
19154
+ `
19155
+ CREATE TABLE account_analytics_accounts (
19156
+ analytics_account_id uuid PRIMARY KEY,
19157
+ organization_id uuid UNIQUE,
19158
+ organization_id_hash text NOT NULL UNIQUE,
19159
+ created_at timestamptz NOT NULL,
19160
+ first_seen_at timestamptz NOT NULL,
19161
+ metrics_collection_started_at timestamptz NOT NULL,
19162
+ backfilled_from_retained_rows_at timestamptz,
19163
+ deleted_at timestamptz,
19164
+ initial_plan text,
19165
+ latest_known_plan text,
19166
+ latest_capacity_units integer,
19167
+ account_deleted boolean NOT NULL DEFAULT false,
19168
+ metrics_schema_version integer NOT NULL DEFAULT 1,
19169
+ updated_at timestamptz NOT NULL DEFAULT now()
19170
+ )
19171
+ `,
19172
+ `
19173
+ CREATE TABLE account_metric_periods (
19174
+ analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
19175
+ period_grain text NOT NULL CHECK (period_grain IN ('day', 'month', 'year', 'lifetime')),
19176
+ period_starts_at timestamptz NOT NULL,
19177
+ metric_key text NOT NULL,
19178
+ metric_value bigint NOT NULL DEFAULT 0,
19179
+ updated_at timestamptz NOT NULL DEFAULT now(),
19180
+ PRIMARY KEY (analytics_account_id, period_grain, period_starts_at, metric_key)
19181
+ )
19182
+ `,
19183
+ `
19184
+ CREATE INDEX account_metric_periods_grain_period_metric_idx
19185
+ ON account_metric_periods (period_grain, period_starts_at, metric_key)
19186
+ `,
19187
+ `
19188
+ CREATE INDEX account_metric_periods_account_grain_period_idx
19189
+ ON account_metric_periods (analytics_account_id, period_grain, period_starts_at)
19190
+ `,
19191
+ `
19192
+ CREATE TABLE account_metric_events (
19193
+ dedupe_key_hash text PRIMARY KEY,
19194
+ analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
19195
+ metric_source text NOT NULL,
19196
+ occurred_at timestamptz NOT NULL,
19197
+ recorded_at timestamptz NOT NULL DEFAULT now(),
19198
+ metric_deltas jsonb NOT NULL
19199
+ )
19200
+ `,
19201
+ `
19202
+ CREATE TABLE account_payment_retention_records (
19203
+ id uuid PRIMARY KEY,
19204
+ analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
19205
+ organization_id_hash text NOT NULL,
19206
+ provider text NOT NULL,
19207
+ plan text,
19208
+ billing_state text,
19209
+ stripe_customer_id text,
19210
+ stripe_subscription_id text,
19211
+ billing_period_starts_at timestamptz,
19212
+ billing_period_ends_at timestamptz,
19213
+ additional_capacity_units integer,
19214
+ last_billing_event_id text,
19215
+ account_deleted_at timestamptz NOT NULL,
19216
+ recorded_at timestamptz NOT NULL DEFAULT now(),
19217
+ updated_at timestamptz NOT NULL DEFAULT now(),
19218
+ UNIQUE (analytics_account_id, provider)
19219
+ )
19220
+ `,
19221
+ `
19222
+ CREATE INDEX account_payment_retention_records_provider_idx
19223
+ ON account_payment_retention_records (provider, account_deleted_at DESC)
19224
+ `,
19225
+ `
19226
+ CREATE TABLE account_payment_provider_events (
19227
+ provider_event_key text PRIMARY KEY,
19228
+ analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
19229
+ organization_id_hash text NOT NULL,
19230
+ provider text NOT NULL,
19231
+ provider_event_id text NOT NULL,
19232
+ provider_event_type text NOT NULL,
19233
+ processed_at timestamptz NOT NULL,
19234
+ account_deleted_at timestamptz NOT NULL,
19235
+ recorded_at timestamptz NOT NULL DEFAULT now()
19236
+ )
19237
+ `,
19238
+ `
19239
+ CREATE UNIQUE INDEX account_payment_provider_events_provider_event_key
19240
+ ON account_payment_provider_events (provider, provider_event_id)
19241
+ `,
18795
19242
  `
18796
19243
  CREATE TABLE operational_email_deliveries (
18797
19244
  id uuid PRIMARY KEY,
@@ -18861,12 +19308,257 @@ var STORAGE_BOOTSTRAP_STATEMENTS = [
18861
19308
  `
18862
19309
  ];
18863
19310
 
19311
+ // ../../packages/storage/src/storage-bootstrap-all-statements.ts
19312
+ var STORAGE_BOOTSTRAP_STATEMENTS2 = [
19313
+ ...STORAGE_BOOTSTRAP_STATEMENTS,
19314
+ ...AVAILABILITY_CHECK_BOOTSTRAP_STATEMENTS
19315
+ ];
19316
+
18864
19317
  // ../../packages/storage/src/migrations.ts
18865
- var STORAGE_BOOTSTRAP_SQL = STORAGE_BOOTSTRAP_STATEMENTS.join(";\n\n");
19318
+ var STORAGE_BOOTSTRAP_SQL = STORAGE_BOOTSTRAP_STATEMENTS2.join(";\n\n");
18866
19319
 
18867
- // ../../packages/storage/src/schema-migrations.ts
19320
+ // ../../packages/storage/src/availability-check-schema-migrations.ts
19321
+ var import_node_crypto2 = require("node:crypto");
19322
+ function defineAvailabilityCheckStorageSchemaMigration(input2) {
19323
+ return {
19324
+ ...input2,
19325
+ checksum: (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify(input2)).digest("hex")
19326
+ };
19327
+ }
19328
+ var AVAILABILITY_CHECK_STORAGE_SCHEMA_MIGRATIONS = [
19329
+ defineAvailabilityCheckStorageSchemaMigration({
19330
+ id: "202606150001_add_availability_checks",
19331
+ description: "Add project-scoped availability checks, result history, and daily rollups.",
19332
+ statements: [
19333
+ `
19334
+ CREATE TABLE IF NOT EXISTS availability_checks (
19335
+ id uuid PRIMARY KEY,
19336
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
19337
+ created_by_user_id uuid REFERENCES users(id) ON DELETE SET NULL,
19338
+ name text NOT NULL,
19339
+ url text NOT NULL,
19340
+ method text NOT NULL,
19341
+ expected_status_min integer NOT NULL DEFAULT 200,
19342
+ expected_status_max integer NOT NULL DEFAULT 399,
19343
+ timeout_ms integer NOT NULL DEFAULT 5000,
19344
+ interval_seconds integer NOT NULL,
19345
+ failure_threshold integer NOT NULL DEFAULT 3,
19346
+ recovery_threshold integer NOT NULL DEFAULT 2,
19347
+ environment text NOT NULL DEFAULT 'production',
19348
+ service_name text,
19349
+ enabled boolean NOT NULL DEFAULT true,
19350
+ status text NOT NULL DEFAULT 'unknown',
19351
+ consecutive_failures integer NOT NULL DEFAULT 0,
19352
+ consecutive_successes integer NOT NULL DEFAULT 0,
19353
+ linked_incident_id uuid REFERENCES incidents(id) ON DELETE SET NULL,
19354
+ last_checked_at timestamptz,
19355
+ next_check_at timestamptz,
19356
+ claimed_at timestamptz,
19357
+ last_result_status text,
19358
+ last_result_http_status integer,
19359
+ last_result_error_kind text,
19360
+ last_result_error_message text,
19361
+ last_result_duration_ms integer,
19362
+ deleted_at timestamptz,
19363
+ created_at timestamptz NOT NULL DEFAULT now(),
19364
+ updated_at timestamptz NOT NULL DEFAULT now()
19365
+ )
19366
+ `,
19367
+ `
19368
+ ALTER TABLE availability_checks
19369
+ DROP CONSTRAINT IF EXISTS availability_checks_method_check
19370
+ `,
19371
+ `
19372
+ ALTER TABLE availability_checks
19373
+ ADD CONSTRAINT availability_checks_method_check
19374
+ CHECK (method IN ('GET', 'HEAD'))
19375
+ `,
19376
+ `
19377
+ ALTER TABLE availability_checks
19378
+ DROP CONSTRAINT IF EXISTS availability_checks_expected_status_min_check
19379
+ `,
19380
+ `
19381
+ ALTER TABLE availability_checks
19382
+ ADD CONSTRAINT availability_checks_expected_status_min_check
19383
+ CHECK (expected_status_min BETWEEN 100 AND 599)
19384
+ `,
19385
+ `
19386
+ ALTER TABLE availability_checks
19387
+ DROP CONSTRAINT IF EXISTS availability_checks_expected_status_max_check
19388
+ `,
19389
+ `
19390
+ ALTER TABLE availability_checks
19391
+ ADD CONSTRAINT availability_checks_expected_status_max_check
19392
+ CHECK (expected_status_max BETWEEN 100 AND 599)
19393
+ `,
19394
+ `
19395
+ ALTER TABLE availability_checks
19396
+ DROP CONSTRAINT IF EXISTS availability_checks_timeout_ms_check
19397
+ `,
19398
+ `
19399
+ ALTER TABLE availability_checks
19400
+ ADD CONSTRAINT availability_checks_timeout_ms_check
19401
+ CHECK (timeout_ms BETWEEN 500 AND 5000)
19402
+ `,
19403
+ `
19404
+ ALTER TABLE availability_checks
19405
+ DROP CONSTRAINT IF EXISTS availability_checks_interval_seconds_check
19406
+ `,
19407
+ `
19408
+ ALTER TABLE availability_checks
19409
+ ADD CONSTRAINT availability_checks_interval_seconds_check
19410
+ CHECK (interval_seconds >= 30)
19411
+ `,
19412
+ `
19413
+ ALTER TABLE availability_checks
19414
+ DROP CONSTRAINT IF EXISTS availability_checks_failure_threshold_check
19415
+ `,
19416
+ `
19417
+ ALTER TABLE availability_checks
19418
+ ADD CONSTRAINT availability_checks_failure_threshold_check
19419
+ CHECK (failure_threshold BETWEEN 1 AND 10)
19420
+ `,
19421
+ `
19422
+ ALTER TABLE availability_checks
19423
+ DROP CONSTRAINT IF EXISTS availability_checks_recovery_threshold_check
19424
+ `,
19425
+ `
19426
+ ALTER TABLE availability_checks
19427
+ ADD CONSTRAINT availability_checks_recovery_threshold_check
19428
+ CHECK (recovery_threshold BETWEEN 1 AND 10)
19429
+ `,
19430
+ `
19431
+ ALTER TABLE availability_checks
19432
+ DROP CONSTRAINT IF EXISTS availability_checks_status_check
19433
+ `,
19434
+ `
19435
+ ALTER TABLE availability_checks
19436
+ ADD CONSTRAINT availability_checks_status_check
19437
+ CHECK (status IN ('unknown', 'passing', 'failing'))
19438
+ `,
19439
+ `
19440
+ ALTER TABLE availability_checks
19441
+ DROP CONSTRAINT IF EXISTS availability_checks_last_result_status_check
19442
+ `,
19443
+ `
19444
+ ALTER TABLE availability_checks
19445
+ ADD CONSTRAINT availability_checks_last_result_status_check
19446
+ CHECK (
19447
+ last_result_status IS NULL OR last_result_status IN (
19448
+ 'success',
19449
+ 'http_status_mismatch',
19450
+ 'timeout',
19451
+ 'dns_error',
19452
+ 'tls_error',
19453
+ 'connection_error',
19454
+ 'redirect_blocked',
19455
+ 'security_blocked',
19456
+ 'internal_error'
19457
+ )
19458
+ )
19459
+ `,
19460
+ `
19461
+ CREATE INDEX IF NOT EXISTS availability_checks_project_created_idx
19462
+ ON availability_checks (project_id, created_at DESC)
19463
+ `,
19464
+ `
19465
+ CREATE INDEX IF NOT EXISTS availability_checks_due_idx
19466
+ ON availability_checks (next_check_at, project_id)
19467
+ `,
19468
+ `
19469
+ CREATE INDEX IF NOT EXISTS availability_checks_claimed_idx
19470
+ ON availability_checks (claimed_at)
19471
+ `,
19472
+ `
19473
+ CREATE TABLE IF NOT EXISTS availability_check_results (
19474
+ id uuid PRIMARY KEY,
19475
+ check_id uuid NOT NULL REFERENCES availability_checks(id) ON DELETE CASCADE,
19476
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
19477
+ started_at timestamptz NOT NULL,
19478
+ completed_at timestamptz NOT NULL,
19479
+ duration_ms integer NOT NULL,
19480
+ status text NOT NULL,
19481
+ http_status integer,
19482
+ error_kind text,
19483
+ error_message text,
19484
+ redirect_count integer NOT NULL DEFAULT 0,
19485
+ checked_url_host text NOT NULL,
19486
+ checked_url_path text NOT NULL,
19487
+ final_url text NOT NULL,
19488
+ created_at timestamptz NOT NULL DEFAULT now()
19489
+ )
19490
+ `,
19491
+ `
19492
+ ALTER TABLE availability_check_results
19493
+ DROP CONSTRAINT IF EXISTS availability_check_results_status_check
19494
+ `,
19495
+ `
19496
+ ALTER TABLE availability_check_results
19497
+ ADD CONSTRAINT availability_check_results_status_check
19498
+ CHECK (
19499
+ status IN (
19500
+ 'success',
19501
+ 'http_status_mismatch',
19502
+ 'timeout',
19503
+ 'dns_error',
19504
+ 'tls_error',
19505
+ 'connection_error',
19506
+ 'redirect_blocked',
19507
+ 'security_blocked',
19508
+ 'internal_error'
19509
+ )
19510
+ )
19511
+ `,
19512
+ `
19513
+ CREATE INDEX IF NOT EXISTS availability_check_results_check_started_idx
19514
+ ON availability_check_results (check_id, started_at DESC)
19515
+ `,
19516
+ `
19517
+ CREATE INDEX IF NOT EXISTS availability_check_results_project_started_idx
19518
+ ON availability_check_results (project_id, started_at DESC)
19519
+ `,
19520
+ `
19521
+ CREATE TABLE IF NOT EXISTS availability_check_daily_rollups (
19522
+ id uuid PRIMARY KEY,
19523
+ check_id uuid NOT NULL REFERENCES availability_checks(id) ON DELETE CASCADE,
19524
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
19525
+ day date NOT NULL,
19526
+ state text NOT NULL,
19527
+ total_checks integer NOT NULL DEFAULT 0,
19528
+ successful_checks integer NOT NULL DEFAULT 0,
19529
+ failed_checks integer NOT NULL DEFAULT 0,
19530
+ degraded_checks integer NOT NULL DEFAULT 0,
19531
+ avg_duration_ms integer,
19532
+ first_checked_at timestamptz,
19533
+ last_checked_at timestamptz,
19534
+ downtime_seconds integer NOT NULL DEFAULT 0,
19535
+ incident_ids uuid[] NOT NULL DEFAULT '{}'::uuid[],
19536
+ created_at timestamptz NOT NULL DEFAULT now(),
19537
+ updated_at timestamptz NOT NULL DEFAULT now(),
19538
+ UNIQUE (check_id, day)
19539
+ )
19540
+ `,
19541
+ `
19542
+ ALTER TABLE availability_check_daily_rollups
19543
+ DROP CONSTRAINT IF EXISTS availability_check_daily_rollups_state_check
19544
+ `,
19545
+ `
19546
+ ALTER TABLE availability_check_daily_rollups
19547
+ ADD CONSTRAINT availability_check_daily_rollups_state_check
19548
+ CHECK (state IN ('unknown', 'operational', 'degraded', 'down', 'paused'))
19549
+ `,
19550
+ `
19551
+ CREATE INDEX IF NOT EXISTS availability_check_daily_rollups_project_day_idx
19552
+ ON availability_check_daily_rollups (project_id, day DESC)
19553
+ `
19554
+ ]
19555
+ })
19556
+ ];
19557
+
19558
+ // ../../packages/storage/src/schema-migrations-catalog.ts
19559
+ var import_node_crypto3 = require("node:crypto");
18868
19560
  function computeMigrationChecksum(input2) {
18869
- return (0, import_node_crypto2.createHash)("sha256").update(JSON.stringify(input2)).digest("hex");
19561
+ return (0, import_node_crypto3.createHash)("sha256").update(JSON.stringify(input2)).digest("hex");
18870
19562
  }
18871
19563
  function defineStorageSchemaMigration(input2) {
18872
19564
  return {
@@ -19560,38 +20252,205 @@ var STORAGE_SCHEMA_MIGRATIONS = [
19560
20252
  statements: [
19561
20253
  "ALTER TABLE capture_policies ADD COLUMN IF NOT EXISTS immediate_client_error_path_rules jsonb"
19562
20254
  ]
19563
- })
19564
- ];
19565
-
19566
- // src/local-retrieval-store.ts
19567
- var CONNECTION_FILE_PATH2 = ".debugbundle/local/connection.json";
19568
- var STATE_FILE_PATH = ".debugbundle/local/state.json";
19569
- function isStringArray(value) {
19570
- return Array.isArray(value) && value.every((item) => typeof item === "string");
19571
- }
19572
- function createReadError(status, code) {
19573
- return new RetrievalApiError(status, code);
19574
- }
19575
- async function readJsonFile(path, dependencies) {
19576
- const readFile = dependencies?.readFile ?? import_promises3.readFile;
19577
- try {
19578
- return JSON.parse(await readFile(path, "utf8"));
19579
- } catch (error) {
19580
- if (isRecord(error) && error["code"] === "ENOENT") {
19581
- throw error;
19582
- }
19583
- throw createReadError(400, "invalid_local_json");
19584
- }
19585
- }
19586
- function parseLocalConnection(candidate) {
19587
- if (!isRecord(candidate) || candidate["mode"] !== "local-only" && candidate["mode"] !== "connected") {
19588
- throw createReadError(400, "invalid_local_connection_config");
19589
- }
19590
- return {
19591
- mode: candidate["mode"]
19592
- };
19593
- }
19594
- function parseLocalIncident(candidate) {
20255
+ }),
20256
+ defineStorageSchemaMigration({
20257
+ id: "202606100001_add_project_usage_counters",
20258
+ description: "Add durable project-level raw ingestion counters for project dashboard metrics.",
20259
+ statements: [
20260
+ `
20261
+ CREATE TABLE IF NOT EXISTS project_usage_counters (
20262
+ project_id uuid NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
20263
+ period_starts_at timestamptz NOT NULL,
20264
+ raw_ingested_events integer NOT NULL DEFAULT 0,
20265
+ updated_at timestamptz NOT NULL DEFAULT now(),
20266
+ PRIMARY KEY (project_id, period_starts_at)
20267
+ )
20268
+ `
20269
+ ]
20270
+ }),
20271
+ defineStorageSchemaMigration({
20272
+ id: "202606100002_add_account_deletion_challenges",
20273
+ description: "Add scoped OTP challenges for account deletion confirmation.",
20274
+ statements: [
20275
+ `
20276
+ CREATE TABLE IF NOT EXISTS account_deletion_challenges (
20277
+ id uuid PRIMARY KEY,
20278
+ organization_id uuid NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
20279
+ user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
20280
+ email text NOT NULL,
20281
+ code_hash text NOT NULL,
20282
+ created_at timestamptz NOT NULL DEFAULT now(),
20283
+ expires_at timestamptz NOT NULL,
20284
+ used_at timestamptz
20285
+ )
20286
+ `,
20287
+ `
20288
+ CREATE INDEX IF NOT EXISTS account_deletion_challenges_scope_idx
20289
+ ON account_deletion_challenges (organization_id, user_id, lower(email), created_at DESC)
20290
+ `,
20291
+ `
20292
+ CREATE INDEX IF NOT EXISTS account_deletion_challenges_code_hash_idx
20293
+ ON account_deletion_challenges (code_hash)
20294
+ `
20295
+ ]
20296
+ }),
20297
+ defineStorageSchemaMigration({
20298
+ id: "202606100003_add_account_analytics_and_payment_retention",
20299
+ description: "Add deletion-safe account analytics and payment retention ledgers.",
20300
+ statements: [
20301
+ `
20302
+ CREATE TABLE IF NOT EXISTS account_analytics_accounts (
20303
+ analytics_account_id uuid PRIMARY KEY,
20304
+ organization_id uuid UNIQUE,
20305
+ organization_id_hash text NOT NULL UNIQUE,
20306
+ created_at timestamptz NOT NULL,
20307
+ first_seen_at timestamptz NOT NULL,
20308
+ metrics_collection_started_at timestamptz NOT NULL,
20309
+ backfilled_from_retained_rows_at timestamptz,
20310
+ deleted_at timestamptz,
20311
+ initial_plan text,
20312
+ latest_known_plan text,
20313
+ latest_capacity_units integer,
20314
+ account_deleted boolean NOT NULL DEFAULT false,
20315
+ metrics_schema_version integer NOT NULL DEFAULT 1,
20316
+ updated_at timestamptz NOT NULL DEFAULT now()
20317
+ )
20318
+ `,
20319
+ `
20320
+ CREATE TABLE IF NOT EXISTS account_metric_periods (
20321
+ analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
20322
+ period_grain text NOT NULL CHECK (period_grain IN ('day', 'month', 'year', 'lifetime')),
20323
+ period_starts_at timestamptz NOT NULL,
20324
+ metric_key text NOT NULL,
20325
+ metric_value bigint NOT NULL DEFAULT 0,
20326
+ updated_at timestamptz NOT NULL DEFAULT now(),
20327
+ PRIMARY KEY (analytics_account_id, period_grain, period_starts_at, metric_key)
20328
+ )
20329
+ `,
20330
+ `
20331
+ CREATE INDEX IF NOT EXISTS account_metric_periods_grain_period_metric_idx
20332
+ ON account_metric_periods (period_grain, period_starts_at, metric_key)
20333
+ `,
20334
+ `
20335
+ CREATE INDEX IF NOT EXISTS account_metric_periods_account_grain_period_idx
20336
+ ON account_metric_periods (analytics_account_id, period_grain, period_starts_at)
20337
+ `,
20338
+ `
20339
+ CREATE TABLE IF NOT EXISTS account_metric_events (
20340
+ dedupe_key_hash text PRIMARY KEY,
20341
+ analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
20342
+ metric_source text NOT NULL,
20343
+ occurred_at timestamptz NOT NULL,
20344
+ recorded_at timestamptz NOT NULL DEFAULT now(),
20345
+ metric_deltas jsonb NOT NULL
20346
+ )
20347
+ `,
20348
+ `
20349
+ CREATE TABLE IF NOT EXISTS account_payment_retention_records (
20350
+ id uuid PRIMARY KEY,
20351
+ analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
20352
+ organization_id_hash text NOT NULL,
20353
+ provider text NOT NULL,
20354
+ plan text,
20355
+ billing_state text,
20356
+ stripe_customer_id text,
20357
+ stripe_subscription_id text,
20358
+ billing_period_starts_at timestamptz,
20359
+ billing_period_ends_at timestamptz,
20360
+ additional_capacity_units integer,
20361
+ last_billing_event_id text,
20362
+ account_deleted_at timestamptz NOT NULL,
20363
+ recorded_at timestamptz NOT NULL DEFAULT now(),
20364
+ updated_at timestamptz NOT NULL DEFAULT now(),
20365
+ UNIQUE (analytics_account_id, provider)
20366
+ )
20367
+ `,
20368
+ `
20369
+ CREATE INDEX IF NOT EXISTS account_payment_retention_records_provider_idx
20370
+ ON account_payment_retention_records (provider, account_deleted_at DESC)
20371
+ `,
20372
+ `
20373
+ CREATE TABLE IF NOT EXISTS account_payment_provider_events (
20374
+ provider_event_key text PRIMARY KEY,
20375
+ analytics_account_id uuid NOT NULL REFERENCES account_analytics_accounts(analytics_account_id),
20376
+ organization_id_hash text NOT NULL,
20377
+ provider text NOT NULL,
20378
+ provider_event_id text NOT NULL,
20379
+ provider_event_type text NOT NULL,
20380
+ processed_at timestamptz NOT NULL,
20381
+ account_deleted_at timestamptz NOT NULL,
20382
+ recorded_at timestamptz NOT NULL DEFAULT now()
20383
+ )
20384
+ `,
20385
+ `
20386
+ CREATE UNIQUE INDEX IF NOT EXISTS account_payment_provider_events_provider_event_key
20387
+ ON account_payment_provider_events (provider, provider_event_id)
20388
+ `
20389
+ ]
20390
+ }),
20391
+ defineStorageSchemaMigration({
20392
+ id: "202606120001_add_session_auth_method",
20393
+ description: "Track the auth method used to create each browser session.",
20394
+ statements: [
20395
+ "ALTER TABLE sessions ADD COLUMN IF NOT EXISTS auth_method text",
20396
+ "ALTER TABLE sessions DROP CONSTRAINT IF EXISTS sessions_auth_method_check",
20397
+ `
20398
+ ALTER TABLE sessions
20399
+ ADD CONSTRAINT sessions_auth_method_check
20400
+ CHECK (auth_method IS NULL OR auth_method IN ('email_code', 'github_oauth'))
20401
+ `
20402
+ ]
20403
+ }),
20404
+ defineStorageSchemaMigration({
20405
+ id: "202606130001_retire_expired_project_invites",
20406
+ description: "Retire already-expired project invites so re-inviting the same email is unblocked.",
20407
+ statements: [
20408
+ `
20409
+ UPDATE project_invites
20410
+ SET canceled_at = expires_at
20411
+ WHERE accepted_at IS NULL
20412
+ AND canceled_at IS NULL
20413
+ AND expires_at <= now()
20414
+ `
20415
+ ]
20416
+ })
20417
+ ];
20418
+
20419
+ // ../../packages/storage/src/schema-migrations.ts
20420
+ var STORAGE_SCHEMA_MIGRATIONS2 = [
20421
+ ...STORAGE_SCHEMA_MIGRATIONS,
20422
+ ...AVAILABILITY_CHECK_STORAGE_SCHEMA_MIGRATIONS
20423
+ ];
20424
+
20425
+ // src/local-retrieval-store.ts
20426
+ var CONNECTION_FILE_PATH2 = ".debugbundle/local/connection.json";
20427
+ var STATE_FILE_PATH = ".debugbundle/local/state.json";
20428
+ function isStringArray(value) {
20429
+ return Array.isArray(value) && value.every((item) => typeof item === "string");
20430
+ }
20431
+ function createReadError(status, code) {
20432
+ return new RetrievalApiError(status, code);
20433
+ }
20434
+ async function readJsonFile(path, dependencies) {
20435
+ const readFile = dependencies?.readFile ?? import_promises3.readFile;
20436
+ try {
20437
+ return JSON.parse(await readFile(path, "utf8"));
20438
+ } catch (error) {
20439
+ if (isRecord(error) && error["code"] === "ENOENT") {
20440
+ throw error;
20441
+ }
20442
+ throw createReadError(400, "invalid_local_json");
20443
+ }
20444
+ }
20445
+ function parseLocalConnection(candidate) {
20446
+ if (!isRecord(candidate) || candidate["mode"] !== "local-only" && candidate["mode"] !== "connected") {
20447
+ throw createReadError(400, "invalid_local_connection_config");
20448
+ }
20449
+ return {
20450
+ mode: candidate["mode"]
20451
+ };
20452
+ }
20453
+ function parseLocalIncident(candidate) {
19595
20454
  if (!isRecord(candidate)) {
19596
20455
  throw createReadError(400, "invalid_local_state");
19597
20456
  }
@@ -19763,7 +20622,7 @@ async function listLocalIncidents(input2, dependencies) {
19763
20622
  return true;
19764
20623
  }
19765
20624
  return incident.status === input2.status;
19766
- }).filter((incident) => input2.severity === void 0 ? true : incident.severity === input2.severity).sort(sortIncidentsDescending);
20625
+ }).filter((incident) => input2.severity === void 0 ? true : incident.severity === input2.severity).filter((incident) => input2.firstSeenAfter === void 0 ? true : incident.first_seen_at >= input2.firstSeenAfter).sort(sortIncidentsDescending);
19767
20626
  const startIndex = input2.cursor === void 0 ? 0 : incidents.findIndex((incident) => buildCursor(incident) === input2.cursor) + 1;
19768
20627
  const pagedIncidents = input2.limit === void 0 ? incidents.slice(startIndex) : incidents.slice(startIndex, startIndex + input2.limit);
19769
20628
  const hasMore = input2.limit !== void 0 && startIndex + input2.limit < incidents.length;
@@ -20307,6 +21166,10 @@ var import_node_path9 = require("node:path");
20307
21166
 
20308
21167
  // ../../packages/project-management-client/src/index.ts
20309
21168
  var ProjectMetricsSchema = external_exports.object({
21169
+ open_incidents: external_exports.number().int().nonnegative().default(0),
21170
+ regressed_incidents: external_exports.number().int().nonnegative().default(0),
21171
+ opened_incidents_today: external_exports.number().int().nonnegative().default(0),
21172
+ opened_incidents_month: external_exports.number().int().nonnegative().default(0),
20310
21173
  monthly_bundle_requests: external_exports.number().int().nonnegative(),
20311
21174
  monthly_raw_ingested_events: external_exports.number().int().nonnegative(),
20312
21175
  retained_bundles: external_exports.number().int().nonnegative(),
@@ -23542,12 +24405,12 @@ async function doctorCommand(input2, dependencies = {}) {
23542
24405
  }
23543
24406
 
23544
24407
  // src/ingest-command.ts
23545
- var import_node_crypto5 = require("node:crypto");
24408
+ var import_node_crypto6 = require("node:crypto");
23546
24409
  var import_promises11 = require("node:fs/promises");
23547
24410
  var import_node_path12 = require("node:path");
23548
24411
 
23549
24412
  // ../../packages/log-parser/src/project-id.ts
23550
- var import_node_crypto3 = require("node:crypto");
24413
+ var import_node_crypto4 = require("node:crypto");
23551
24414
  var INGEST_SDK = {
23552
24415
  name: "debugbundle-ingest",
23553
24416
  version: "0.1.0"
@@ -23557,7 +24420,7 @@ function slugify(value) {
23557
24420
  return normalized.length > 0 ? normalized : "application";
23558
24421
  }
23559
24422
  function buildDeterministicUuid(parts) {
23560
- const digest = (0, import_node_crypto3.createHash)("sha256").update(parts.join("\0")).digest();
24423
+ const digest = (0, import_node_crypto4.createHash)("sha256").update(parts.join("\0")).digest();
23561
24424
  const bytes = Uint8Array.from(digest.subarray(0, 16));
23562
24425
  bytes[6] = (bytes[6] ?? 0) & 15 | 80;
23563
24426
  bytes[8] = (bytes[8] ?? 0) & 63 | 128;
@@ -23862,7 +24725,7 @@ function parseLogFile(content, input2) {
23862
24725
  }
23863
24726
 
23864
24727
  // src/process-command.ts
23865
- var import_node_crypto4 = require("node:crypto");
24728
+ var import_node_crypto5 = require("node:crypto");
23866
24729
  var import_promises10 = require("node:fs/promises");
23867
24730
  var import_node_path11 = require("node:path");
23868
24731
 
@@ -25036,7 +25899,7 @@ function mergeAggregateGroup(aggregates) {
25036
25899
  });
25037
25900
  }
25038
25901
  function hashIdentifier(parts, prefix, length) {
25039
- const digest = (0, import_node_crypto4.createHash)("sha256").update(parts.join("\0")).digest("hex");
25902
+ const digest = (0, import_node_crypto5.createHash)("sha256").update(parts.join("\0")).digest("hex");
25040
25903
  return `${prefix}_${digest.slice(0, length)}`;
25041
25904
  }
25042
25905
  function deriveIncidentId(projectId, serviceName, environment, incidentFingerprint) {
@@ -25070,7 +25933,7 @@ function stableJson3(value) {
25070
25933
  return `{${keys.map((key) => `${JSON.stringify(key)}:${stableJson3(record[key])}`).join(",")}}`;
25071
25934
  }
25072
25935
  function buildRequestAnomalyFingerprint(input2) {
25073
- return (0, import_node_crypto4.createHash)("sha256").update(
25936
+ return (0, import_node_crypto5.createHash)("sha256").update(
25074
25937
  stableJson3({
25075
25938
  kind: "request_status_anomaly",
25076
25939
  project_id: input2.projectId,
@@ -25704,7 +26567,7 @@ function buildEventFileName(events, filePath) {
25704
26567
  const candidate = Date.parse(event.occurred_at);
25705
26568
  return Number.isFinite(candidate) && candidate > latest ? candidate : latest;
25706
26569
  }, 0);
25707
- const digest = (0, import_node_crypto5.createHash)("sha256").update([filePath, ...events.map((event) => event.event_id)].join("\0")).digest("hex").slice(0, 8);
26570
+ const digest = (0, import_node_crypto6.createHash)("sha256").update([filePath, ...events.map((event) => event.event_id)].join("\0")).digest("hex").slice(0, 8);
25708
26571
  return `${lastOccurredAt}-${digest}-${slugify2(events[0]?.service.name ?? (0, import_node_path12.basename)(filePath))}.events.json`;
25709
26572
  }
25710
26573
  function formatHumanOutput(summary) {
@@ -27321,6 +28184,7 @@ async function listAllCloudIncidents(input2, api) {
27321
28184
  ...input2.service === void 0 ? {} : { service: input2.service },
27322
28185
  ...input2.status === void 0 ? {} : { status: input2.status },
27323
28186
  ...input2.severity === void 0 ? {} : { severity: input2.severity },
28187
+ ...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter },
27324
28188
  ...cursor === void 0 ? {} : { cursor }
27325
28189
  });
27326
28190
  incidents.push(
@@ -27341,7 +28205,8 @@ async function mapCombinedIncidentListResult(input2, api, dependencies) {
27341
28205
  ...input2.environment === void 0 ? {} : { environment: input2.environment },
27342
28206
  ...input2.service === void 0 ? {} : { service: input2.service },
27343
28207
  ...input2.status === void 0 ? {} : { status: input2.status },
27344
- ...input2.severity === void 0 ? {} : { severity: input2.severity }
28208
+ ...input2.severity === void 0 ? {} : { severity: input2.severity },
28209
+ ...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter }
27345
28210
  },
27346
28211
  dependencies
27347
28212
  );
@@ -27352,7 +28217,8 @@ async function mapCombinedIncidentListResult(input2, api, dependencies) {
27352
28217
  ...input2.environment === void 0 ? {} : { environment: input2.environment },
27353
28218
  ...input2.service === void 0 ? {} : { service: input2.service },
27354
28219
  ...input2.status === void 0 ? {} : { status: input2.status },
27355
- ...input2.severity === void 0 ? {} : { severity: input2.severity }
28220
+ ...input2.severity === void 0 ? {} : { severity: input2.severity },
28221
+ ...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter }
27356
28222
  },
27357
28223
  api
27358
28224
  );
@@ -27391,6 +28257,9 @@ async function listIncidentsCommand(input2, api) {
27391
28257
  if (input2.severity !== void 0) {
27392
28258
  requestInput.severity = input2.severity;
27393
28259
  }
28260
+ if (input2.firstSeenAfter !== void 0) {
28261
+ requestInput.firstSeenAfter = input2.firstSeenAfter;
28262
+ }
27394
28263
  if (input2.cursor !== void 0) {
27395
28264
  requestInput.cursor = input2.cursor;
27396
28265
  }
@@ -27422,6 +28291,7 @@ async function listIncidentsWithAuthCommand(input2, dependencies) {
27422
28291
  ...input2.service === void 0 ? {} : { service: input2.service },
27423
28292
  ...input2.status === void 0 ? {} : { status: input2.status },
27424
28293
  ...input2.severity === void 0 ? {} : { severity: input2.severity },
28294
+ ...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter },
27425
28295
  ...input2.cursor === void 0 ? {} : { cursor: input2.cursor },
27426
28296
  ...input2.limit === void 0 ? {} : { limit: input2.limit }
27427
28297
  },
@@ -27446,6 +28316,7 @@ async function listIncidentsWithAuthCommand(input2, dependencies) {
27446
28316
  ...input2.service === void 0 ? {} : { service: input2.service },
27447
28317
  ...input2.status === void 0 ? {} : { status: input2.status },
27448
28318
  ...input2.severity === void 0 ? {} : { severity: input2.severity },
28319
+ ...input2.firstSeenAfter === void 0 ? {} : { firstSeenAfter: input2.firstSeenAfter },
27449
28320
  ...input2.cursor === void 0 ? {} : { cursor: input2.cursor },
27450
28321
  ...input2.limit === void 0 ? {} : { limit: input2.limit },
27451
28322
  ...input2.json === void 0 ? {} : { json: input2.json }
@@ -27481,6 +28352,9 @@ async function listIncidentsWithAuthCommand(input2, dependencies) {
27481
28352
  if (input2.severity !== void 0) {
27482
28353
  commandInput.severity = input2.severity;
27483
28354
  }
28355
+ if (input2.firstSeenAfter !== void 0) {
28356
+ commandInput.firstSeenAfter = input2.firstSeenAfter;
28357
+ }
27484
28358
  if (input2.cursor !== void 0) {
27485
28359
  commandInput.cursor = input2.cursor;
27486
28360
  }
@@ -28241,7 +29115,7 @@ async function listServicesWithAuthCommand(input2, dependencies) {
28241
29115
  }
28242
29116
 
28243
29117
  // src/verify-command.ts
28244
- var import_node_crypto6 = require("node:crypto");
29118
+ var import_node_crypto7 = require("node:crypto");
28245
29119
  var import_promises15 = require("node:fs/promises");
28246
29120
  var import_node_path17 = require("node:path");
28247
29121
  function resolveOverallStatus2(checks) {
@@ -28386,7 +29260,7 @@ function cloudVerificationRunId(now) {
28386
29260
  return now.toISOString().replace(/[-:.TZ]/g, "").slice(0, 14);
28387
29261
  }
28388
29262
  function defaultCloudVerificationSuffix() {
28389
- return (0, import_node_crypto6.randomUUID)().replace(/-/g, "").slice(0, 12);
29263
+ return (0, import_node_crypto7.randomUUID)().replace(/-/g, "").slice(0, 12);
28390
29264
  }
28391
29265
  function normalizeCloudVerificationSuffix(suffix) {
28392
29266
  const normalized = suffix.toLowerCase().replace(/[^a-z0-9]/g, "").slice(0, 12);
@@ -29205,7 +30079,7 @@ var CLI_USAGE_LINES = [
29205
30079
  " debugbundle login --github-device [--label <label>] [--base-url <url>] [--auth-file <path>] [--json]",
29206
30080
  " debugbundle profile validate [--json]",
29207
30081
  " debugbundle whoami [--auth-file <path>] [--json]",
29208
- " debugbundle incidents [--source <local|cloud>] [--project-id <id>] [--environment <name>] [--service <name>] [--status <status>] [--severity <severity>] [--cursor <cursor>] [--limit <n>] [--auth-file <path>] [--json]",
30082
+ " debugbundle incidents [--source <local|cloud>] [--project-id <id>] [--environment <name>] [--service <name>] [--status <status>] [--severity <severity>] [--first-seen-after <ISO8601>] [--cursor <cursor>] [--limit <n>] [--auth-file <path>] [--json]",
29209
30083
  " debugbundle inspect <incident-id> [--source <local|cloud>] [--auth-file <path>] [--json]",
29210
30084
  " debugbundle explain <incident-id> [--source <local|cloud>] [--auth-file <path>] [--json]",
29211
30085
  " debugbundle resolve <incident-id> [incident-id ...] [--source <local|cloud>] [--auth-file <path>] [--json]",
@@ -29278,6 +30152,14 @@ var CLI_USAGE_LINES = [
29278
30152
  " debugbundle probe activate <project-id> --label-pattern <pattern> [--service <name>] [--environment <name>] [--ttl-seconds <n>] [--trigger-ttl-seconds <n>] [--auth-file <path>] [--json]",
29279
30153
  " debugbundle probe list <project-id> [--auth-file <path>] [--json]",
29280
30154
  " debugbundle probe deactivate <project-id> <activation-id> [--auth-file <path>] [--json]",
30155
+ " debugbundle health checks list --project-id <id> [--limit <n>] [--auth-file <path>] [--json]",
30156
+ " debugbundle health checks get <check-id> --project-id <id> [--auth-file <path>] [--json]",
30157
+ " 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]",
30158
+ " 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]",
30159
+ " debugbundle health checks delete <check-id> --project-id <id> [--auth-file <path>] [--json]",
30160
+ " 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]",
30161
+ " debugbundle health checks results <check-id> --project-id <id> [--limit <n>] [--auth-file <path>] [--json]",
30162
+ " debugbundle health checks daily-rollups <check-id> --project-id <id> [--limit <n>] [--auth-file <path>] [--json]",
29281
30163
  " debugbundle project members list --project-id <id> [--auth-file <path>] [--json]",
29282
30164
  " debugbundle project members invites --project-id <id> [--auth-file <path>] [--json]",
29283
30165
  " debugbundle project members invite --project-id <id> --email <email> --role <admin|member> [--auth-file <path>] [--json]",
@@ -32166,58 +33048,25 @@ async function handleTokenCommand(parsedArgv, dependencies) {
32166
33048
  throw new CliInputError("Unknown token command.");
32167
33049
  }
32168
33050
 
32169
- // src/capture-policy-commands.ts
32170
- var CapturePolicyApiError = class extends Error {
33051
+ // src/health-check-commands.ts
33052
+ var HealthCheckApiError = class extends Error {
32171
33053
  status;
32172
- constructor(status, message) {
32173
- super(message);
32174
- this.name = "CapturePolicyApiError";
33054
+ code;
33055
+ constructor(status, code) {
33056
+ super(`health_check_api_error: ${status}:${code}`);
33057
+ this.name = "HealthCheckApiError";
32175
33058
  this.status = status;
33059
+ this.code = code;
32176
33060
  }
32177
33061
  };
32178
- function toApiError3(status, body, fallback) {
33062
+ function toApiError3(status, body) {
32179
33063
  if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
32180
- return new CapturePolicyApiError(status, body.error);
33064
+ return new HealthCheckApiError(status, body.error);
32181
33065
  }
32182
- return new CapturePolicyApiError(status, fallback);
32183
- }
32184
- function createCapturePolicyApi(httpClient) {
32185
- return {
32186
- async getCapturePolicy(input2) {
32187
- const response = await httpClient.request({
32188
- method: "GET",
32189
- path: `/v1/projects/${encodeURIComponent(input2.projectId)}/capture-policy`,
32190
- bearerToken: input2.bearerToken
32191
- });
32192
- if (response.status !== 200) {
32193
- throw toApiError3(response.status, response.body, "Failed to get capture policy.");
32194
- }
32195
- const parsed = CapturePolicyResponseSchema.safeParse(response.body);
32196
- if (!parsed.success) {
32197
- throw new CapturePolicyApiError(500, "Invalid capture policy response.");
32198
- }
32199
- return parsed.data;
32200
- },
32201
- async updateCapturePolicy(input2) {
32202
- const response = await httpClient.request({
32203
- method: "PATCH",
32204
- path: `/v1/projects/${encodeURIComponent(input2.projectId)}/capture-policy`,
32205
- bearerToken: input2.bearerToken,
32206
- body: input2.update
32207
- });
32208
- if (response.status !== 200) {
32209
- throw toApiError3(response.status, response.body, "Failed to update capture policy.");
32210
- }
32211
- const parsed = CapturePolicyResponseSchema.safeParse(response.body);
32212
- if (!parsed.success) {
32213
- throw new CapturePolicyApiError(500, "Invalid capture policy response.");
32214
- }
32215
- return parsed.data;
32216
- }
32217
- };
33066
+ return new HealthCheckApiError(status, "unknown_error");
32218
33067
  }
32219
33068
  function mapErrorToExitCode11(error) {
32220
- if (!(error instanceof CapturePolicyApiError)) {
33069
+ if (!(error instanceof HealthCheckApiError)) {
32221
33070
  return 1;
32222
33071
  }
32223
33072
  if (error.status === 401) {
@@ -32229,108 +33078,893 @@ function mapErrorToExitCode11(error) {
32229
33078
  if (error.status === 400) {
32230
33079
  return 4;
32231
33080
  }
33081
+ if (error.status === 403 || error.status === 409) {
33082
+ return 5;
33083
+ }
33084
+ if (error.status === 429) {
33085
+ return 6;
33086
+ }
32232
33087
  return 1;
32233
33088
  }
32234
- function statusesEqual(left, right) {
32235
- if (left.length !== right.length) {
32236
- return false;
33089
+ function buildCreateRequestBody(input2) {
33090
+ const body = {
33091
+ name: input2.name,
33092
+ url: input2.url,
33093
+ method: input2.method,
33094
+ expected_status_min: input2.expectedStatusMin,
33095
+ expected_status_max: input2.expectedStatusMax,
33096
+ timeout_ms: input2.timeoutMs,
33097
+ interval_seconds: input2.intervalSeconds,
33098
+ failure_threshold: input2.failureThreshold,
33099
+ recovery_threshold: input2.recoveryThreshold,
33100
+ enabled: input2.enabled
33101
+ };
33102
+ if (input2.environment !== void 0) {
33103
+ body["environment"] = input2.environment;
32237
33104
  }
32238
- return left.every((value, index) => value === right[index]);
32239
- }
32240
- function formatStatusList(statuses) {
32241
- return statuses.length === 0 ? "none" : statuses.join(", ");
32242
- }
32243
- function formatClientErrorPathRules(response) {
32244
- const rawOverride = response.overrides.immediate_client_error_path_rules ?? null;
32245
- const rules = rawOverride ?? response.policy.immediate_client_error_path_rules ?? [];
32246
- if (rules.length === 0) {
32247
- return rawOverride === null ? "preset default (none)" : "none (explicit)";
33105
+ if (input2.serviceName !== void 0) {
33106
+ body["service_name"] = input2.serviceName;
32248
33107
  }
32249
- const formatted = rules.map((rule) => {
32250
- const methods = rule.methods.length === 0 ? "" : `@${rule.methods.join(",")}`;
32251
- return `${rule.status_code}=${rule.path_pattern}${methods}`;
32252
- });
32253
- return `${rawOverride === null ? "preset default" : "custom"} (${formatted.join("; ")})`;
33108
+ return body;
32254
33109
  }
32255
- function formatClientErrorIncidents(response) {
32256
- const rawOverride = response.overrides.immediate_client_error_statuses;
32257
- if (rawOverride === null) {
32258
- return `preset default (${formatStatusList(response.policy.immediate_client_error_statuses)})`;
33110
+ function buildUpdateRequestBody(input2) {
33111
+ const body = {};
33112
+ if (input2.name !== void 0) {
33113
+ body["name"] = input2.name;
32259
33114
  }
32260
- if (rawOverride.length === 0) {
32261
- return "none (explicit)";
33115
+ if (input2.url !== void 0) {
33116
+ body["url"] = input2.url;
32262
33117
  }
32263
- if (statusesEqual(rawOverride, RECOMMENDED_IMMEDIATE_CLIENT_ERROR_STATUSES)) {
32264
- return `recommended (${formatStatusList(rawOverride)})`;
33118
+ if (input2.method !== void 0) {
33119
+ body["method"] = input2.method;
32265
33120
  }
32266
- return `custom (${formatStatusList(rawOverride)})`;
32267
- }
32268
- function formatPolicy(response) {
32269
- const policy = response.policy;
32270
- return [
32271
- `preset: ${policy.preset}`,
32272
- `capture_logs: ${policy.capture_logs}`,
32273
- `capture_request_events: ${policy.capture_request_events}`,
32274
- `capture_breadcrumbs: ${policy.capture_breadcrumbs}`,
32275
- `capture_probe_events: ${policy.capture_probe_events}`,
32276
- `client_error_incidents: ${formatClientErrorIncidents(response)}`,
32277
- `client_error_path_rules: ${formatClientErrorPathRules(response)}`
32278
- ].join("\n");
32279
- }
32280
- async function getCapturePolicyCommand(input2, api) {
32281
- try {
32282
- const response = await api.getCapturePolicy({
32283
- bearerToken: input2.bearerToken,
32284
- projectId: input2.projectId
32285
- });
32286
- return {
32287
- exitCode: 0,
32288
- output: input2.json ? JSON.stringify(response) : formatPolicy(response)
32289
- };
32290
- } catch (error) {
32291
- return {
32292
- exitCode: mapErrorToExitCode11(error),
32293
- output: error instanceof Error ? error.message : String(error)
32294
- };
33121
+ if (input2.expectedStatusMin !== void 0) {
33122
+ body["expected_status_min"] = input2.expectedStatusMin;
32295
33123
  }
32296
- }
32297
- async function setCapturePolicyCommand(input2, api) {
32298
- try {
32299
- const parsedUpdate = CapturePolicyUpdateSchema.safeParse(input2.update);
32300
- if (!parsedUpdate.success) {
32301
- return {
32302
- exitCode: 4,
32303
- output: "Invalid capture policy update."
32304
- };
32305
- }
32306
- const response = await api.updateCapturePolicy({
32307
- bearerToken: input2.bearerToken,
32308
- projectId: input2.projectId,
32309
- update: parsedUpdate.data
32310
- });
32311
- return {
32312
- exitCode: 0,
32313
- output: input2.json ? JSON.stringify(response) : `Capture policy updated.
32314
- ${formatPolicy(response)}`
32315
- };
32316
- } catch (error) {
32317
- return {
32318
- exitCode: mapErrorToExitCode11(error),
32319
- output: error instanceof Error ? error.message : String(error)
32320
- };
33124
+ if (input2.expectedStatusMax !== void 0) {
33125
+ body["expected_status_max"] = input2.expectedStatusMax;
32321
33126
  }
32322
- }
32323
- async function createAuthenticatedCapturePolicyApi(input2, dependencies) {
32324
- const readAuthState = dependencies?.readAuthState ?? readCliAuthState;
32325
- const authStateInput = {};
32326
- if (input2.authFilePath !== void 0) {
32327
- authStateInput.authFilePath = input2.authFilePath;
33127
+ if (input2.timeoutMs !== void 0) {
33128
+ body["timeout_ms"] = input2.timeoutMs;
32328
33129
  }
32329
- const authState = await readAuthState(authStateInput);
32330
- const createHttpClient = dependencies?.createHttpClient ?? ((clientInput) => {
32331
- const httpClientDependencies = {};
32332
- if (dependencies?.fetchImpl !== void 0) {
32333
- httpClientDependencies.fetchImpl = dependencies.fetchImpl;
33130
+ if (input2.intervalSeconds !== void 0) {
33131
+ body["interval_seconds"] = input2.intervalSeconds;
33132
+ }
33133
+ if (input2.failureThreshold !== void 0) {
33134
+ body["failure_threshold"] = input2.failureThreshold;
33135
+ }
33136
+ if (input2.recoveryThreshold !== void 0) {
33137
+ body["recovery_threshold"] = input2.recoveryThreshold;
33138
+ }
33139
+ if (input2.environment !== void 0) {
33140
+ body["environment"] = input2.environment;
33141
+ }
33142
+ if (input2.serviceName !== void 0) {
33143
+ body["service_name"] = input2.serviceName;
33144
+ }
33145
+ if (input2.enabled !== void 0) {
33146
+ body["enabled"] = input2.enabled;
33147
+ }
33148
+ return body;
33149
+ }
33150
+ function createHealthCheckApi(httpClient) {
33151
+ return {
33152
+ async listHealthChecks(input2) {
33153
+ const limit = input2.limit ?? 100;
33154
+ const response = await httpClient.request({
33155
+ method: "GET",
33156
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks?limit=${encodeURIComponent(String(limit))}`,
33157
+ bearerToken: input2.bearerToken
33158
+ });
33159
+ if (response.status !== 200) {
33160
+ throw toApiError3(response.status, response.body);
33161
+ }
33162
+ return response.body;
33163
+ },
33164
+ async getHealthCheck(input2) {
33165
+ const response = await httpClient.request({
33166
+ method: "GET",
33167
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks/${encodeURIComponent(input2.checkId)}`,
33168
+ bearerToken: input2.bearerToken
33169
+ });
33170
+ if (response.status !== 200) {
33171
+ throw toApiError3(response.status, response.body);
33172
+ }
33173
+ return response.body;
33174
+ },
33175
+ async createHealthCheck(input2) {
33176
+ const response = await httpClient.request({
33177
+ method: "POST",
33178
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks`,
33179
+ bearerToken: input2.bearerToken,
33180
+ body: buildCreateRequestBody(input2)
33181
+ });
33182
+ if (response.status !== 201) {
33183
+ throw toApiError3(response.status, response.body);
33184
+ }
33185
+ return response.body;
33186
+ },
33187
+ async updateHealthCheck(input2) {
33188
+ const response = await httpClient.request({
33189
+ method: "PATCH",
33190
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks/${encodeURIComponent(input2.checkId)}`,
33191
+ bearerToken: input2.bearerToken,
33192
+ body: buildUpdateRequestBody(input2)
33193
+ });
33194
+ if (response.status !== 200) {
33195
+ throw toApiError3(response.status, response.body);
33196
+ }
33197
+ return response.body;
33198
+ },
33199
+ async deleteHealthCheck(input2) {
33200
+ const response = await httpClient.request({
33201
+ method: "DELETE",
33202
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks/${encodeURIComponent(input2.checkId)}`,
33203
+ bearerToken: input2.bearerToken
33204
+ });
33205
+ if (response.status !== 200) {
33206
+ throw toApiError3(response.status, response.body);
33207
+ }
33208
+ return response.body;
33209
+ },
33210
+ async testHealthCheck(input2) {
33211
+ const response = await httpClient.request({
33212
+ method: "POST",
33213
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks/test`,
33214
+ bearerToken: input2.bearerToken,
33215
+ body: {
33216
+ url: input2.url,
33217
+ method: input2.method,
33218
+ expected_status_min: input2.expectedStatusMin,
33219
+ expected_status_max: input2.expectedStatusMax,
33220
+ timeout_ms: input2.timeoutMs
33221
+ }
33222
+ });
33223
+ if (response.status !== 200) {
33224
+ throw toApiError3(response.status, response.body);
33225
+ }
33226
+ return response.body;
33227
+ },
33228
+ async listHealthCheckResults(input2) {
33229
+ const limit = input2.limit ?? 20;
33230
+ const response = await httpClient.request({
33231
+ method: "GET",
33232
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks/${encodeURIComponent(input2.checkId)}/results?limit=${encodeURIComponent(String(limit))}`,
33233
+ bearerToken: input2.bearerToken
33234
+ });
33235
+ if (response.status !== 200) {
33236
+ throw toApiError3(response.status, response.body);
33237
+ }
33238
+ return response.body;
33239
+ },
33240
+ async listHealthCheckDailyRollups(input2) {
33241
+ const limit = input2.limit ?? 30;
33242
+ const response = await httpClient.request({
33243
+ method: "GET",
33244
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/availability-checks/${encodeURIComponent(input2.checkId)}/daily-rollups?limit=${encodeURIComponent(String(limit))}`,
33245
+ bearerToken: input2.bearerToken
33246
+ });
33247
+ if (response.status !== 200) {
33248
+ throw toApiError3(response.status, response.body);
33249
+ }
33250
+ return response.body;
33251
+ }
33252
+ };
33253
+ }
33254
+ function formatServiceAndEnvironment(check) {
33255
+ return `${check.service_name ?? "availability"}/${check.environment}`;
33256
+ }
33257
+ function formatNullable(value) {
33258
+ return value === null ? "-" : String(value);
33259
+ }
33260
+ function formatCheckSummary(check) {
33261
+ 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}`}`;
33262
+ return [
33263
+ `${check.check_id} ${check.name} [${check.status}]`,
33264
+ `${check.method} ${check.url}`,
33265
+ `interval=${check.interval_seconds}s timeout=${check.timeout_ms}ms expected=${check.expected_status_min}-${check.expected_status_max}`,
33266
+ `service=${formatServiceAndEnvironment(check)} enabled=${check.enabled ? "true" : "false"} last=${lastResult}`
33267
+ ].join("\n");
33268
+ }
33269
+ function formatCheckResultSummary(result) {
33270
+ return [
33271
+ `${result.started_at} ${result.status}`,
33272
+ `http=${formatNullable(result.http_status)} duration=${result.duration_ms}ms redirects=${result.redirect_count}`,
33273
+ `host=${result.checked_url_host} final=${result.final_url}`
33274
+ ].join(" ");
33275
+ }
33276
+ function formatCheckDailyRollupSummary(rollup) {
33277
+ return [
33278
+ `${rollup.day} ${rollup.state}`,
33279
+ `checks=${rollup.total_checks}`,
33280
+ `success=${rollup.successful_checks}`,
33281
+ `failed=${rollup.failed_checks}`,
33282
+ `degraded=${rollup.degraded_checks}`,
33283
+ `avg=${formatNullable(rollup.avg_duration_ms)}ms`,
33284
+ `downtime=${rollup.downtime_seconds}s`
33285
+ ].join(" ");
33286
+ }
33287
+ function formatTestResult(result) {
33288
+ return [
33289
+ `Test result: ${result.result.status}`,
33290
+ `http=${formatNullable(result.result.http_status)}`,
33291
+ `duration=${result.result.duration_ms}ms`,
33292
+ `host=${result.result.checked_url_host}`,
33293
+ `final=${result.result.final_url}`
33294
+ ].join(" ");
33295
+ }
33296
+ async function listHealthChecksCommand(input2, api) {
33297
+ try {
33298
+ const result = await api.listHealthChecks({
33299
+ bearerToken: input2.bearerToken,
33300
+ projectId: input2.projectId,
33301
+ ...input2.limit === void 0 ? {} : { limit: input2.limit }
33302
+ });
33303
+ if (input2.json) {
33304
+ return { exitCode: 0, output: JSON.stringify(result) };
33305
+ }
33306
+ if (result.checks.length === 0) {
33307
+ return {
33308
+ exitCode: 0,
33309
+ output: `No health checks.
33310
+ Plan limits: ${result.limits.max_checks_per_project} checks, minimum interval ${result.limits.min_interval_seconds}s.`
33311
+ };
33312
+ }
33313
+ return {
33314
+ exitCode: 0,
33315
+ output: result.checks.map(formatCheckSummary).join("\n\n")
33316
+ };
33317
+ } catch (error) {
33318
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33319
+ }
33320
+ }
33321
+ async function getHealthCheckCommand(input2, api) {
33322
+ try {
33323
+ const result = await api.getHealthCheck({
33324
+ bearerToken: input2.bearerToken,
33325
+ projectId: input2.projectId,
33326
+ checkId: input2.checkId
33327
+ });
33328
+ if (input2.json) {
33329
+ return { exitCode: 0, output: JSON.stringify(result) };
33330
+ }
33331
+ return {
33332
+ exitCode: 0,
33333
+ output: `${formatCheckSummary(result.check)}
33334
+ limits=${result.limits.max_checks_per_project} min_interval=${result.limits.min_interval_seconds}s`
33335
+ };
33336
+ } catch (error) {
33337
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33338
+ }
33339
+ }
33340
+ async function createHealthCheckCommand(input2, api) {
33341
+ try {
33342
+ const result = await api.createHealthCheck(input2);
33343
+ if (input2.json) {
33344
+ return { exitCode: 0, output: JSON.stringify(result) };
33345
+ }
33346
+ return {
33347
+ exitCode: 0,
33348
+ output: `Health check created: ${result.check.check_id} (${result.check.name})`
33349
+ };
33350
+ } catch (error) {
33351
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33352
+ }
33353
+ }
33354
+ async function updateHealthCheckCommand(input2, api) {
33355
+ try {
33356
+ const result = await api.updateHealthCheck(input2);
33357
+ if (input2.json) {
33358
+ return { exitCode: 0, output: JSON.stringify(result) };
33359
+ }
33360
+ return {
33361
+ exitCode: 0,
33362
+ output: `Health check updated: ${result.check.check_id} (${result.check.name})`
33363
+ };
33364
+ } catch (error) {
33365
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33366
+ }
33367
+ }
33368
+ async function deleteHealthCheckCommand(input2, api) {
33369
+ try {
33370
+ const result = await api.deleteHealthCheck({
33371
+ bearerToken: input2.bearerToken,
33372
+ projectId: input2.projectId,
33373
+ checkId: input2.checkId
33374
+ });
33375
+ if (input2.json) {
33376
+ return { exitCode: 0, output: JSON.stringify(result) };
33377
+ }
33378
+ return {
33379
+ exitCode: 0,
33380
+ output: result.deleted ? "Health check deleted." : "Health check was already deleted."
33381
+ };
33382
+ } catch (error) {
33383
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33384
+ }
33385
+ }
33386
+ async function testHealthCheckCommand(input2, api) {
33387
+ try {
33388
+ const result = await api.testHealthCheck(input2);
33389
+ if (input2.json) {
33390
+ return { exitCode: 0, output: JSON.stringify(result) };
33391
+ }
33392
+ return {
33393
+ exitCode: 0,
33394
+ output: formatTestResult(result)
33395
+ };
33396
+ } catch (error) {
33397
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33398
+ }
33399
+ }
33400
+ async function listHealthCheckResultsCommand(input2, api) {
33401
+ try {
33402
+ const result = await api.listHealthCheckResults({
33403
+ bearerToken: input2.bearerToken,
33404
+ projectId: input2.projectId,
33405
+ checkId: input2.checkId,
33406
+ ...input2.limit === void 0 ? {} : { limit: input2.limit }
33407
+ });
33408
+ if (input2.json) {
33409
+ return { exitCode: 0, output: JSON.stringify(result) };
33410
+ }
33411
+ if (result.results.length === 0) {
33412
+ return { exitCode: 0, output: "No health check results." };
33413
+ }
33414
+ return {
33415
+ exitCode: 0,
33416
+ output: result.results.map(formatCheckResultSummary).join("\n")
33417
+ };
33418
+ } catch (error) {
33419
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33420
+ }
33421
+ }
33422
+ async function listHealthCheckDailyRollupsCommand(input2, api) {
33423
+ try {
33424
+ const result = await api.listHealthCheckDailyRollups({
33425
+ bearerToken: input2.bearerToken,
33426
+ projectId: input2.projectId,
33427
+ checkId: input2.checkId,
33428
+ ...input2.limit === void 0 ? {} : { limit: input2.limit }
33429
+ });
33430
+ if (input2.json) {
33431
+ return { exitCode: 0, output: JSON.stringify(result) };
33432
+ }
33433
+ if (result.rollups.length === 0) {
33434
+ return { exitCode: 0, output: "No health check daily rollups." };
33435
+ }
33436
+ return {
33437
+ exitCode: 0,
33438
+ output: result.rollups.map(formatCheckDailyRollupSummary).join("\n")
33439
+ };
33440
+ } catch (error) {
33441
+ return { exitCode: mapErrorToExitCode11(error), output: error instanceof Error ? error.message : String(error) };
33442
+ }
33443
+ }
33444
+ async function createAuthenticatedHealthCheckApi(input2, dependencies) {
33445
+ const readAuth = dependencies?.readAuthState ?? readCliAuthState;
33446
+ const authStateInput = {};
33447
+ if (input2.authFilePath !== void 0) {
33448
+ authStateInput.authFilePath = input2.authFilePath;
33449
+ }
33450
+ const authState = await readAuth(authStateInput);
33451
+ const createHttpClient = dependencies?.createHttpClient ?? ((clientInput) => createCliHttpClient(clientInput));
33452
+ const httpClient = createHttpClient({ baseUrl: authState.base_url });
33453
+ const createApi = dependencies?.createApi ?? createHealthCheckApi;
33454
+ return { authState, api: createApi(httpClient) };
33455
+ }
33456
+ async function listHealthChecksWithAuthCommand(input2, dependencies) {
33457
+ return runAuthenticatedCliCommand(input2, {
33458
+ createApi: createAuthenticatedHealthCheckApi,
33459
+ dependencies,
33460
+ runCommand: (authState, api) => listHealthChecksCommand(
33461
+ {
33462
+ bearerToken: authState.bearer_token,
33463
+ projectId: input2.projectId,
33464
+ ...input2.limit === void 0 ? {} : { limit: input2.limit },
33465
+ ...input2.json === void 0 ? {} : { json: input2.json }
33466
+ },
33467
+ { listHealthChecks: (requestInput) => api.listHealthChecks(requestInput) }
33468
+ )
33469
+ });
33470
+ }
33471
+ async function getHealthCheckWithAuthCommand(input2, dependencies) {
33472
+ return runAuthenticatedCliCommand(input2, {
33473
+ createApi: createAuthenticatedHealthCheckApi,
33474
+ dependencies,
33475
+ runCommand: (authState, api) => getHealthCheckCommand(
33476
+ {
33477
+ bearerToken: authState.bearer_token,
33478
+ projectId: input2.projectId,
33479
+ checkId: input2.checkId,
33480
+ ...input2.json === void 0 ? {} : { json: input2.json }
33481
+ },
33482
+ { getHealthCheck: (requestInput) => api.getHealthCheck(requestInput) }
33483
+ )
33484
+ });
33485
+ }
33486
+ async function createHealthCheckWithAuthCommand(input2, dependencies) {
33487
+ return runAuthenticatedCliCommand(input2, {
33488
+ createApi: createAuthenticatedHealthCheckApi,
33489
+ dependencies,
33490
+ runCommand: (authState, api) => {
33491
+ const commandInput = {
33492
+ ...input2,
33493
+ bearerToken: authState.bearer_token
33494
+ };
33495
+ return createHealthCheckCommand(commandInput, {
33496
+ createHealthCheck: (requestInput) => api.createHealthCheck(requestInput)
33497
+ });
33498
+ }
33499
+ });
33500
+ }
33501
+ async function updateHealthCheckWithAuthCommand(input2, dependencies) {
33502
+ return runAuthenticatedCliCommand(input2, {
33503
+ createApi: createAuthenticatedHealthCheckApi,
33504
+ dependencies,
33505
+ runCommand: (authState, api) => {
33506
+ const commandInput = {
33507
+ ...input2,
33508
+ bearerToken: authState.bearer_token
33509
+ };
33510
+ return updateHealthCheckCommand(commandInput, {
33511
+ updateHealthCheck: (requestInput) => api.updateHealthCheck(requestInput)
33512
+ });
33513
+ }
33514
+ });
33515
+ }
33516
+ async function deleteHealthCheckWithAuthCommand(input2, dependencies) {
33517
+ return runAuthenticatedCliCommand(input2, {
33518
+ createApi: createAuthenticatedHealthCheckApi,
33519
+ dependencies,
33520
+ runCommand: (authState, api) => deleteHealthCheckCommand(
33521
+ {
33522
+ bearerToken: authState.bearer_token,
33523
+ projectId: input2.projectId,
33524
+ checkId: input2.checkId,
33525
+ ...input2.json === void 0 ? {} : { json: input2.json }
33526
+ },
33527
+ { deleteHealthCheck: (requestInput) => api.deleteHealthCheck(requestInput) }
33528
+ )
33529
+ });
33530
+ }
33531
+ async function testHealthCheckWithAuthCommand(input2, dependencies) {
33532
+ return runAuthenticatedCliCommand(input2, {
33533
+ createApi: createAuthenticatedHealthCheckApi,
33534
+ dependencies,
33535
+ runCommand: (authState, api) => {
33536
+ const commandInput = {
33537
+ ...input2,
33538
+ bearerToken: authState.bearer_token
33539
+ };
33540
+ return testHealthCheckCommand(commandInput, {
33541
+ testHealthCheck: (requestInput) => api.testHealthCheck(requestInput)
33542
+ });
33543
+ }
33544
+ });
33545
+ }
33546
+ async function listHealthCheckResultsWithAuthCommand(input2, dependencies) {
33547
+ return runAuthenticatedCliCommand(input2, {
33548
+ createApi: createAuthenticatedHealthCheckApi,
33549
+ dependencies,
33550
+ runCommand: (authState, api) => listHealthCheckResultsCommand(
33551
+ {
33552
+ bearerToken: authState.bearer_token,
33553
+ projectId: input2.projectId,
33554
+ checkId: input2.checkId,
33555
+ ...input2.limit === void 0 ? {} : { limit: input2.limit },
33556
+ ...input2.json === void 0 ? {} : { json: input2.json }
33557
+ },
33558
+ { listHealthCheckResults: (requestInput) => api.listHealthCheckResults(requestInput) }
33559
+ )
33560
+ });
33561
+ }
33562
+ async function listHealthCheckDailyRollupsWithAuthCommand(input2, dependencies) {
33563
+ return runAuthenticatedCliCommand(input2, {
33564
+ createApi: createAuthenticatedHealthCheckApi,
33565
+ dependencies,
33566
+ runCommand: (authState, api) => listHealthCheckDailyRollupsCommand(
33567
+ {
33568
+ bearerToken: authState.bearer_token,
33569
+ projectId: input2.projectId,
33570
+ checkId: input2.checkId,
33571
+ ...input2.limit === void 0 ? {} : { limit: input2.limit },
33572
+ ...input2.json === void 0 ? {} : { json: input2.json }
33573
+ },
33574
+ { listHealthCheckDailyRollups: (requestInput) => api.listHealthCheckDailyRollups(requestInput) }
33575
+ )
33576
+ });
33577
+ }
33578
+
33579
+ // src/management-health-command-handlers.ts
33580
+ function readOptionalServiceName(parsedArgv) {
33581
+ const service = readStringOption(parsedArgv, "service");
33582
+ if (service === void 0) {
33583
+ return void 0;
33584
+ }
33585
+ return service === "null" ? null : service;
33586
+ }
33587
+ function readRequiredProjectId(parsedArgv) {
33588
+ const projectId = readStringOption(parsedArgv, "project-id");
33589
+ if (projectId === void 0) {
33590
+ throw new CliInputError("Missing required option --project-id.");
33591
+ }
33592
+ return projectId;
33593
+ }
33594
+ function readRequiredUrl(parsedArgv) {
33595
+ const url = readStringOption(parsedArgv, "url");
33596
+ if (url === void 0) {
33597
+ throw new CliInputError("Missing required option --url.");
33598
+ }
33599
+ return url;
33600
+ }
33601
+ function readRequiredName(parsedArgv) {
33602
+ const name = readStringOption(parsedArgv, "name");
33603
+ if (name === void 0) {
33604
+ throw new CliInputError("Missing required option --name.");
33605
+ }
33606
+ return name;
33607
+ }
33608
+ async function handleHealthCommand(parsedArgv, dependencies) {
33609
+ const resource = requirePositional(parsedArgv, 1, "resource");
33610
+ if (resource !== "checks") {
33611
+ throw new CliInputError("Unknown health command.");
33612
+ }
33613
+ const action = requirePositional(parsedArgv, 2, "action");
33614
+ if (action === "list") {
33615
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id", "limit"]);
33616
+ ensureNoExtraPositionals(parsedArgv, 3);
33617
+ const limit = readLimitOption(parsedArgv);
33618
+ return await (dependencies.listHealthChecksCommand ?? listHealthChecksWithAuthCommand)(
33619
+ appendCommonAuthOptions(parsedArgv, {
33620
+ projectId: readRequiredProjectId(parsedArgv),
33621
+ ...limit === void 0 ? {} : { limit }
33622
+ })
33623
+ );
33624
+ }
33625
+ if (action === "get") {
33626
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id"]);
33627
+ ensureNoExtraPositionals(parsedArgv, 4);
33628
+ return await (dependencies.getHealthCheckCommand ?? getHealthCheckWithAuthCommand)(
33629
+ appendCommonAuthOptions(parsedArgv, {
33630
+ projectId: readRequiredProjectId(parsedArgv),
33631
+ checkId: requirePositional(parsedArgv, 3, "check-id")
33632
+ })
33633
+ );
33634
+ }
33635
+ if (action === "create") {
33636
+ expectNoUnknownOptions(parsedArgv, [
33637
+ "auth-file",
33638
+ "json",
33639
+ "project-id",
33640
+ "name",
33641
+ "url",
33642
+ "method",
33643
+ "expected-status-min",
33644
+ "expected-status-max",
33645
+ "timeout-ms",
33646
+ "interval-seconds",
33647
+ "failure-threshold",
33648
+ "recovery-threshold",
33649
+ "environment",
33650
+ "service",
33651
+ "enabled"
33652
+ ]);
33653
+ ensureNoExtraPositionals(parsedArgv, 3);
33654
+ const intervalSeconds = readIntegerOption(parsedArgv, "interval-seconds");
33655
+ if (intervalSeconds === void 0) {
33656
+ throw new CliInputError("Missing required option --interval-seconds.");
33657
+ }
33658
+ const method = readStringOption(parsedArgv, "method") ?? "GET";
33659
+ if (method !== "GET" && method !== "HEAD") {
33660
+ throw new CliInputError("Invalid value for --method.");
33661
+ }
33662
+ const enabled = readBooleanStringOption(parsedArgv, "enabled") ?? true;
33663
+ const environment = readStringOption(parsedArgv, "environment");
33664
+ const serviceName = readOptionalServiceName(parsedArgv);
33665
+ return await (dependencies.createHealthCheckCommand ?? createHealthCheckWithAuthCommand)(
33666
+ appendCommonAuthOptions(parsedArgv, {
33667
+ projectId: readRequiredProjectId(parsedArgv),
33668
+ name: readRequiredName(parsedArgv),
33669
+ url: readRequiredUrl(parsedArgv),
33670
+ method,
33671
+ expectedStatusMin: readIntegerOption(parsedArgv, "expected-status-min") ?? 200,
33672
+ expectedStatusMax: readIntegerOption(parsedArgv, "expected-status-max") ?? 399,
33673
+ timeoutMs: readIntegerOption(parsedArgv, "timeout-ms") ?? 5e3,
33674
+ intervalSeconds,
33675
+ failureThreshold: readIntegerOption(parsedArgv, "failure-threshold") ?? 3,
33676
+ recoveryThreshold: readIntegerOption(parsedArgv, "recovery-threshold") ?? 2,
33677
+ ...environment === void 0 ? {} : { environment },
33678
+ ...serviceName === void 0 ? {} : { serviceName },
33679
+ enabled
33680
+ })
33681
+ );
33682
+ }
33683
+ if (action === "update") {
33684
+ expectNoUnknownOptions(parsedArgv, [
33685
+ "auth-file",
33686
+ "json",
33687
+ "project-id",
33688
+ "name",
33689
+ "url",
33690
+ "method",
33691
+ "expected-status-min",
33692
+ "expected-status-max",
33693
+ "timeout-ms",
33694
+ "interval-seconds",
33695
+ "failure-threshold",
33696
+ "recovery-threshold",
33697
+ "environment",
33698
+ "service",
33699
+ "enabled"
33700
+ ]);
33701
+ ensureNoExtraPositionals(parsedArgv, 4);
33702
+ const method = readStringOption(parsedArgv, "method");
33703
+ if (method !== void 0 && method !== "GET" && method !== "HEAD") {
33704
+ throw new CliInputError("Invalid value for --method.");
33705
+ }
33706
+ const input2 = appendCommonAuthOptions(parsedArgv, {
33707
+ projectId: readRequiredProjectId(parsedArgv),
33708
+ checkId: requirePositional(parsedArgv, 3, "check-id")
33709
+ });
33710
+ const name = readStringOption(parsedArgv, "name");
33711
+ const url = readStringOption(parsedArgv, "url");
33712
+ const expectedStatusMin = readIntegerOption(parsedArgv, "expected-status-min");
33713
+ const expectedStatusMax = readIntegerOption(parsedArgv, "expected-status-max");
33714
+ const timeoutMs = readIntegerOption(parsedArgv, "timeout-ms");
33715
+ const intervalSeconds = readIntegerOption(parsedArgv, "interval-seconds");
33716
+ const failureThreshold = readIntegerOption(parsedArgv, "failure-threshold");
33717
+ const recoveryThreshold = readIntegerOption(parsedArgv, "recovery-threshold");
33718
+ const environment = readStringOption(parsedArgv, "environment");
33719
+ const serviceName = readOptionalServiceName(parsedArgv);
33720
+ const enabled = readBooleanStringOption(parsedArgv, "enabled");
33721
+ if (name !== void 0) input2.name = name;
33722
+ if (url !== void 0) input2.url = url;
33723
+ if (method !== void 0) input2.method = method;
33724
+ if (expectedStatusMin !== void 0) input2.expectedStatusMin = expectedStatusMin;
33725
+ if (expectedStatusMax !== void 0) input2.expectedStatusMax = expectedStatusMax;
33726
+ if (timeoutMs !== void 0) input2.timeoutMs = timeoutMs;
33727
+ if (intervalSeconds !== void 0) input2.intervalSeconds = intervalSeconds;
33728
+ if (failureThreshold !== void 0) input2.failureThreshold = failureThreshold;
33729
+ if (recoveryThreshold !== void 0) input2.recoveryThreshold = recoveryThreshold;
33730
+ if (environment !== void 0) input2.environment = environment;
33731
+ if (serviceName !== void 0) input2.serviceName = serviceName;
33732
+ if (enabled !== void 0) input2.enabled = enabled;
33733
+ 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;
33734
+ if (!hasChanges) {
33735
+ throw new CliInputError("At least one health-check field must be provided.");
33736
+ }
33737
+ return await (dependencies.updateHealthCheckCommand ?? updateHealthCheckWithAuthCommand)(input2);
33738
+ }
33739
+ if (action === "delete") {
33740
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id"]);
33741
+ ensureNoExtraPositionals(parsedArgv, 4);
33742
+ return await (dependencies.deleteHealthCheckCommand ?? deleteHealthCheckWithAuthCommand)(
33743
+ appendCommonAuthOptions(parsedArgv, {
33744
+ projectId: readRequiredProjectId(parsedArgv),
33745
+ checkId: requirePositional(parsedArgv, 3, "check-id")
33746
+ })
33747
+ );
33748
+ }
33749
+ if (action === "test") {
33750
+ expectNoUnknownOptions(parsedArgv, [
33751
+ "auth-file",
33752
+ "json",
33753
+ "project-id",
33754
+ "url",
33755
+ "method",
33756
+ "expected-status-min",
33757
+ "expected-status-max",
33758
+ "timeout-ms"
33759
+ ]);
33760
+ ensureNoExtraPositionals(parsedArgv, 3);
33761
+ const method = readStringOption(parsedArgv, "method") ?? "GET";
33762
+ if (method !== "GET" && method !== "HEAD") {
33763
+ throw new CliInputError("Invalid value for --method.");
33764
+ }
33765
+ return await (dependencies.testHealthCheckCommand ?? testHealthCheckWithAuthCommand)(
33766
+ appendCommonAuthOptions(parsedArgv, {
33767
+ projectId: readRequiredProjectId(parsedArgv),
33768
+ url: readRequiredUrl(parsedArgv),
33769
+ method,
33770
+ expectedStatusMin: readIntegerOption(parsedArgv, "expected-status-min") ?? 200,
33771
+ expectedStatusMax: readIntegerOption(parsedArgv, "expected-status-max") ?? 399,
33772
+ timeoutMs: readIntegerOption(parsedArgv, "timeout-ms") ?? 5e3
33773
+ })
33774
+ );
33775
+ }
33776
+ if (action === "results") {
33777
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id", "limit"]);
33778
+ ensureNoExtraPositionals(parsedArgv, 4);
33779
+ const limit = readLimitOption(parsedArgv);
33780
+ return await (dependencies.listHealthCheckResultsCommand ?? listHealthCheckResultsWithAuthCommand)(
33781
+ appendCommonAuthOptions(parsedArgv, {
33782
+ projectId: readRequiredProjectId(parsedArgv),
33783
+ checkId: requirePositional(parsedArgv, 3, "check-id"),
33784
+ ...limit === void 0 ? {} : { limit }
33785
+ })
33786
+ );
33787
+ }
33788
+ if (action === "daily-rollups") {
33789
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "project-id", "limit"]);
33790
+ ensureNoExtraPositionals(parsedArgv, 4);
33791
+ const limit = readLimitOption(parsedArgv);
33792
+ return await (dependencies.listHealthCheckDailyRollupsCommand ?? listHealthCheckDailyRollupsWithAuthCommand)(
33793
+ appendCommonAuthOptions(parsedArgv, {
33794
+ projectId: readRequiredProjectId(parsedArgv),
33795
+ checkId: requirePositional(parsedArgv, 3, "check-id"),
33796
+ ...limit === void 0 ? {} : { limit }
33797
+ })
33798
+ );
33799
+ }
33800
+ throw new CliInputError("Unknown health checks command.");
33801
+ }
33802
+
33803
+ // src/capture-policy-commands.ts
33804
+ var CapturePolicyApiError = class extends Error {
33805
+ status;
33806
+ constructor(status, message) {
33807
+ super(message);
33808
+ this.name = "CapturePolicyApiError";
33809
+ this.status = status;
33810
+ }
33811
+ };
33812
+ function toApiError4(status, body, fallback) {
33813
+ if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
33814
+ return new CapturePolicyApiError(status, body.error);
33815
+ }
33816
+ return new CapturePolicyApiError(status, fallback);
33817
+ }
33818
+ function createCapturePolicyApi(httpClient) {
33819
+ return {
33820
+ async getCapturePolicy(input2) {
33821
+ const response = await httpClient.request({
33822
+ method: "GET",
33823
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/capture-policy`,
33824
+ bearerToken: input2.bearerToken
33825
+ });
33826
+ if (response.status !== 200) {
33827
+ throw toApiError4(response.status, response.body, "Failed to get capture policy.");
33828
+ }
33829
+ const parsed = CapturePolicyResponseSchema.safeParse(response.body);
33830
+ if (!parsed.success) {
33831
+ throw new CapturePolicyApiError(500, "Invalid capture policy response.");
33832
+ }
33833
+ return parsed.data;
33834
+ },
33835
+ async updateCapturePolicy(input2) {
33836
+ const response = await httpClient.request({
33837
+ method: "PATCH",
33838
+ path: `/v1/projects/${encodeURIComponent(input2.projectId)}/capture-policy`,
33839
+ bearerToken: input2.bearerToken,
33840
+ body: input2.update
33841
+ });
33842
+ if (response.status !== 200) {
33843
+ throw toApiError4(response.status, response.body, "Failed to update capture policy.");
33844
+ }
33845
+ const parsed = CapturePolicyResponseSchema.safeParse(response.body);
33846
+ if (!parsed.success) {
33847
+ throw new CapturePolicyApiError(500, "Invalid capture policy response.");
33848
+ }
33849
+ return parsed.data;
33850
+ }
33851
+ };
33852
+ }
33853
+ function mapErrorToExitCode12(error) {
33854
+ if (!(error instanceof CapturePolicyApiError)) {
33855
+ return 1;
33856
+ }
33857
+ if (error.status === 401) {
33858
+ return 2;
33859
+ }
33860
+ if (error.status === 404) {
33861
+ return 3;
33862
+ }
33863
+ if (error.status === 400) {
33864
+ return 4;
33865
+ }
33866
+ return 1;
33867
+ }
33868
+ function statusesEqual(left, right) {
33869
+ if (left.length !== right.length) {
33870
+ return false;
33871
+ }
33872
+ return left.every((value, index) => value === right[index]);
33873
+ }
33874
+ function formatStatusList(statuses) {
33875
+ return statuses.length === 0 ? "none" : statuses.join(", ");
33876
+ }
33877
+ function formatClientErrorPathRules(response) {
33878
+ const rawOverride = response.overrides.immediate_client_error_path_rules ?? null;
33879
+ const rules = rawOverride ?? response.policy.immediate_client_error_path_rules ?? [];
33880
+ if (rules.length === 0) {
33881
+ return rawOverride === null ? "preset default (none)" : "none (explicit)";
33882
+ }
33883
+ const formatted = rules.map((rule) => {
33884
+ const methods = rule.methods.length === 0 ? "" : `@${rule.methods.join(",")}`;
33885
+ return `${rule.status_code}=${rule.path_pattern}${methods}`;
33886
+ });
33887
+ return `${rawOverride === null ? "preset default" : "custom"} (${formatted.join("; ")})`;
33888
+ }
33889
+ function formatClientErrorIncidents(response) {
33890
+ const rawOverride = response.overrides.immediate_client_error_statuses;
33891
+ if (rawOverride === null) {
33892
+ return `preset default (${formatStatusList(response.policy.immediate_client_error_statuses)})`;
33893
+ }
33894
+ if (rawOverride.length === 0) {
33895
+ return "none (explicit)";
33896
+ }
33897
+ if (statusesEqual(rawOverride, RECOMMENDED_IMMEDIATE_CLIENT_ERROR_STATUSES)) {
33898
+ return `recommended (${formatStatusList(rawOverride)})`;
33899
+ }
33900
+ return `custom (${formatStatusList(rawOverride)})`;
33901
+ }
33902
+ function formatPolicy(response) {
33903
+ const policy = response.policy;
33904
+ return [
33905
+ `preset: ${policy.preset}`,
33906
+ `capture_logs: ${policy.capture_logs}`,
33907
+ `capture_request_events: ${policy.capture_request_events}`,
33908
+ `capture_breadcrumbs: ${policy.capture_breadcrumbs}`,
33909
+ `capture_probe_events: ${policy.capture_probe_events}`,
33910
+ `client_error_incidents: ${formatClientErrorIncidents(response)}`,
33911
+ `client_error_path_rules: ${formatClientErrorPathRules(response)}`
33912
+ ].join("\n");
33913
+ }
33914
+ async function getCapturePolicyCommand(input2, api) {
33915
+ try {
33916
+ const response = await api.getCapturePolicy({
33917
+ bearerToken: input2.bearerToken,
33918
+ projectId: input2.projectId
33919
+ });
33920
+ return {
33921
+ exitCode: 0,
33922
+ output: input2.json ? JSON.stringify(response) : formatPolicy(response)
33923
+ };
33924
+ } catch (error) {
33925
+ return {
33926
+ exitCode: mapErrorToExitCode12(error),
33927
+ output: error instanceof Error ? error.message : String(error)
33928
+ };
33929
+ }
33930
+ }
33931
+ async function setCapturePolicyCommand(input2, api) {
33932
+ try {
33933
+ const parsedUpdate = CapturePolicyUpdateSchema.safeParse(input2.update);
33934
+ if (!parsedUpdate.success) {
33935
+ return {
33936
+ exitCode: 4,
33937
+ output: "Invalid capture policy update."
33938
+ };
33939
+ }
33940
+ const response = await api.updateCapturePolicy({
33941
+ bearerToken: input2.bearerToken,
33942
+ projectId: input2.projectId,
33943
+ update: parsedUpdate.data
33944
+ });
33945
+ return {
33946
+ exitCode: 0,
33947
+ output: input2.json ? JSON.stringify(response) : `Capture policy updated.
33948
+ ${formatPolicy(response)}`
33949
+ };
33950
+ } catch (error) {
33951
+ return {
33952
+ exitCode: mapErrorToExitCode12(error),
33953
+ output: error instanceof Error ? error.message : String(error)
33954
+ };
33955
+ }
33956
+ }
33957
+ async function createAuthenticatedCapturePolicyApi(input2, dependencies) {
33958
+ const readAuthState = dependencies?.readAuthState ?? readCliAuthState;
33959
+ const authStateInput = {};
33960
+ if (input2.authFilePath !== void 0) {
33961
+ authStateInput.authFilePath = input2.authFilePath;
33962
+ }
33963
+ const authState = await readAuthState(authStateInput);
33964
+ const createHttpClient = dependencies?.createHttpClient ?? ((clientInput) => {
33965
+ const httpClientDependencies = {};
33966
+ if (dependencies?.fetchImpl !== void 0) {
33967
+ httpClientDependencies.fetchImpl = dependencies.fetchImpl;
32334
33968
  }
32335
33969
  return createCliHttpClient(clientInput, httpClientDependencies);
32336
33970
  });
@@ -32388,7 +34022,7 @@ var CaptureRuleApiError = class extends Error {
32388
34022
  this.status = status;
32389
34023
  }
32390
34024
  };
32391
- function toApiError4(status, body, fallback) {
34025
+ function toApiError5(status, body, fallback) {
32392
34026
  if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
32393
34027
  return new CaptureRuleApiError(status, body.error);
32394
34028
  }
@@ -32403,7 +34037,7 @@ function createCaptureRuleApi(httpClient) {
32403
34037
  bearerToken: input2.bearerToken
32404
34038
  });
32405
34039
  if (response.status !== 200) {
32406
- throw toApiError4(response.status, response.body, "Failed to list capture rules.");
34040
+ throw toApiError5(response.status, response.body, "Failed to list capture rules.");
32407
34041
  }
32408
34042
  const parsed = CaptureRulesResponseSchema.safeParse(response.body);
32409
34043
  if (!parsed.success) {
@@ -32419,7 +34053,7 @@ function createCaptureRuleApi(httpClient) {
32419
34053
  body: input2.create
32420
34054
  });
32421
34055
  if (response.status !== 201) {
32422
- throw toApiError4(response.status, response.body, "Failed to create capture rule.");
34056
+ throw toApiError5(response.status, response.body, "Failed to create capture rule.");
32423
34057
  }
32424
34058
  const parsed = CaptureRuleResponseSchema.safeParse(response.body);
32425
34059
  if (!parsed.success) {
@@ -32434,7 +34068,7 @@ function createCaptureRuleApi(httpClient) {
32434
34068
  bearerToken: input2.bearerToken
32435
34069
  });
32436
34070
  if (response.status !== 200) {
32437
- throw toApiError4(response.status, response.body, "Failed to suggest capture rules.");
34071
+ throw toApiError5(response.status, response.body, "Failed to suggest capture rules.");
32438
34072
  }
32439
34073
  const parsed = CaptureRuleSuggestionsResponseSchema.safeParse(response.body);
32440
34074
  if (!parsed.success) {
@@ -32450,7 +34084,7 @@ function createCaptureRuleApi(httpClient) {
32450
34084
  body: input2.create
32451
34085
  });
32452
34086
  if (response.status !== 201) {
32453
- throw toApiError4(response.status, response.body, "Failed to create capture rule from suggestion.");
34087
+ throw toApiError5(response.status, response.body, "Failed to create capture rule from suggestion.");
32454
34088
  }
32455
34089
  const parsed = CaptureRuleResponseSchema.safeParse(response.body);
32456
34090
  if (!parsed.success) {
@@ -32466,7 +34100,7 @@ function createCaptureRuleApi(httpClient) {
32466
34100
  body: input2.update
32467
34101
  });
32468
34102
  if (response.status !== 200) {
32469
- throw toApiError4(response.status, response.body, "Failed to update capture rule.");
34103
+ throw toApiError5(response.status, response.body, "Failed to update capture rule.");
32470
34104
  }
32471
34105
  const parsed = CaptureRuleResponseSchema.safeParse(response.body);
32472
34106
  if (!parsed.success) {
@@ -32481,7 +34115,7 @@ function createCaptureRuleApi(httpClient) {
32481
34115
  bearerToken: input2.bearerToken
32482
34116
  });
32483
34117
  if (response.status !== 200) {
32484
- throw toApiError4(response.status, response.body, "Failed to delete capture rule.");
34118
+ throw toApiError5(response.status, response.body, "Failed to delete capture rule.");
32485
34119
  }
32486
34120
  if (typeof response.body !== "object" || response.body === null || !("success" in response.body) || response.body.success !== true) {
32487
34121
  throw new CaptureRuleApiError(500, "Invalid capture rule delete response.");
@@ -32490,7 +34124,7 @@ function createCaptureRuleApi(httpClient) {
32490
34124
  }
32491
34125
  };
32492
34126
  }
32493
- function mapErrorToExitCode12(error) {
34127
+ function mapErrorToExitCode13(error) {
32494
34128
  if (!(error instanceof CaptureRuleApiError)) {
32495
34129
  return 1;
32496
34130
  }
@@ -32614,7 +34248,7 @@ async function listCaptureRulesCommand(input2, api) {
32614
34248
  };
32615
34249
  } catch (error) {
32616
34250
  return {
32617
- exitCode: mapErrorToExitCode12(error),
34251
+ exitCode: mapErrorToExitCode13(error),
32618
34252
  output: error instanceof Error ? error.message : String(error)
32619
34253
  };
32620
34254
  }
@@ -32640,7 +34274,7 @@ ${formatRule(response.rule)}`
32640
34274
  };
32641
34275
  } catch (error) {
32642
34276
  return {
32643
- exitCode: mapErrorToExitCode12(error),
34277
+ exitCode: mapErrorToExitCode13(error),
32644
34278
  output: error instanceof Error ? error.message : String(error)
32645
34279
  };
32646
34280
  }
@@ -32657,7 +34291,7 @@ async function suggestCaptureRulesFromIncidentCommand(input2, api) {
32657
34291
  };
32658
34292
  } catch (error) {
32659
34293
  return {
32660
- exitCode: mapErrorToExitCode12(error),
34294
+ exitCode: mapErrorToExitCode13(error),
32661
34295
  output: error instanceof Error ? error.message : String(error)
32662
34296
  };
32663
34297
  }
@@ -32683,7 +34317,7 @@ ${formatRule(response.rule)}`
32683
34317
  };
32684
34318
  } catch (error) {
32685
34319
  return {
32686
- exitCode: mapErrorToExitCode12(error),
34320
+ exitCode: mapErrorToExitCode13(error),
32687
34321
  output: error instanceof Error ? error.message : String(error)
32688
34322
  };
32689
34323
  }
@@ -32710,7 +34344,7 @@ ${formatRule(response.rule)}`
32710
34344
  };
32711
34345
  } catch (error) {
32712
34346
  return {
32713
- exitCode: mapErrorToExitCode12(error),
34347
+ exitCode: mapErrorToExitCode13(error),
32714
34348
  output: error instanceof Error ? error.message : String(error)
32715
34349
  };
32716
34350
  }
@@ -32728,7 +34362,7 @@ async function deleteCaptureRuleCommand(input2, api) {
32728
34362
  };
32729
34363
  } catch (error) {
32730
34364
  return {
32731
- exitCode: mapErrorToExitCode12(error),
34365
+ exitCode: mapErrorToExitCode13(error),
32732
34366
  output: error instanceof Error ? error.message : String(error)
32733
34367
  };
32734
34368
  }
@@ -32855,7 +34489,7 @@ var ProbeApiError = class extends Error {
32855
34489
  this.code = code;
32856
34490
  }
32857
34491
  };
32858
- function toApiError5(status, body) {
34492
+ function toApiError6(status, body) {
32859
34493
  if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
32860
34494
  return new ProbeApiError(status, body.error);
32861
34495
  }
@@ -32886,7 +34520,7 @@ function createProbeApi(httpClient) {
32886
34520
  body
32887
34521
  });
32888
34522
  if (response.status !== 201) {
32889
- throw toApiError5(response.status, response.body);
34523
+ throw toApiError6(response.status, response.body);
32890
34524
  }
32891
34525
  return response.body;
32892
34526
  },
@@ -32897,7 +34531,7 @@ function createProbeApi(httpClient) {
32897
34531
  bearerToken: input2.bearerToken
32898
34532
  });
32899
34533
  if (response.status !== 200) {
32900
- throw toApiError5(response.status, response.body);
34534
+ throw toApiError6(response.status, response.body);
32901
34535
  }
32902
34536
  return response.body;
32903
34537
  },
@@ -32909,13 +34543,13 @@ function createProbeApi(httpClient) {
32909
34543
  body: { activation_id: input2.activationId }
32910
34544
  });
32911
34545
  if (response.status !== 200) {
32912
- throw toApiError5(response.status, response.body);
34546
+ throw toApiError6(response.status, response.body);
32913
34547
  }
32914
34548
  return response.body;
32915
34549
  }
32916
34550
  };
32917
34551
  }
32918
- function mapErrorToExitCode13(error) {
34552
+ function mapErrorToExitCode14(error) {
32919
34553
  if (!(error instanceof ProbeApiError)) {
32920
34554
  return 1;
32921
34555
  }
@@ -32968,7 +34602,7 @@ async function activateProbeCommand(input2, api) {
32968
34602
  Trigger token: ${result.trigger_token}`
32969
34603
  };
32970
34604
  } catch (error) {
32971
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
34605
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
32972
34606
  }
32973
34607
  }
32974
34608
  async function listActiveProbesCommand(input2, api) {
@@ -32988,7 +34622,7 @@ async function listActiveProbesCommand(input2, api) {
32988
34622
  output: result.activations.map((a) => `${a.activation_id} ${a.label_pattern} (${a.service}/${a.environment}) expires ${a.expires_at}`).join("\n")
32989
34623
  };
32990
34624
  } catch (error) {
32991
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
34625
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
32992
34626
  }
32993
34627
  }
32994
34628
  async function deactivateProbeCommand(input2, api) {
@@ -33006,7 +34640,7 @@ async function deactivateProbeCommand(input2, api) {
33006
34640
  output: result.deactivated ? "Probe deactivated." : "Probe was already inactive."
33007
34641
  };
33008
34642
  } catch (error) {
33009
- return { exitCode: mapErrorToExitCode13(error), output: error instanceof Error ? error.message : String(error) };
34643
+ return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
33010
34644
  }
33011
34645
  }
33012
34646
  async function createAuthenticatedProbeApi(input2, dependencies) {
@@ -33441,7 +35075,7 @@ function handleMemberCommand(parsedArgv, dependencies) {
33441
35075
  }
33442
35076
 
33443
35077
  // src/alert-commands.ts
33444
- function mapErrorToExitCode14(error) {
35078
+ function mapErrorToExitCode15(error) {
33445
35079
  if (!(error instanceof AlertApiError)) {
33446
35080
  return 1;
33447
35081
  }
@@ -33479,7 +35113,7 @@ async function listAlertsCommand(input2, api) {
33479
35113
  output: input2.json ? JSON.stringify({ alerts }) : formatAlertTable(alerts)
33480
35114
  };
33481
35115
  } catch (error) {
33482
- return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
35116
+ return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
33483
35117
  }
33484
35118
  }
33485
35119
  async function listAlertsWithAuthCommand(input2, dependencies) {
@@ -33530,7 +35164,7 @@ async function createAlertCommand(input2, api) {
33530
35164
  output: input2.json ? JSON.stringify({ alert }) : `Alert created: ${alert.alert_id}`
33531
35165
  };
33532
35166
  } catch (error) {
33533
- return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
35167
+ return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
33534
35168
  }
33535
35169
  }
33536
35170
  async function createAlertWithAuthCommand(input2, dependencies) {
@@ -33600,7 +35234,7 @@ async function updateAlertCommand(input2, api) {
33600
35234
  output: input2.json ? JSON.stringify({ alert }) : `Alert updated: ${alert.alert_id}`
33601
35235
  };
33602
35236
  } catch (error) {
33603
- return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
35237
+ return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
33604
35238
  }
33605
35239
  }
33606
35240
  async function updateAlertWithAuthCommand(input2, dependencies) {
@@ -33655,7 +35289,7 @@ async function deleteAlertCommand(input2, api) {
33655
35289
  output: input2.json ? JSON.stringify({ alert }) : `Alert deleted: ${alert.alert_id}`
33656
35290
  };
33657
35291
  } catch (error) {
33658
- return { exitCode: mapErrorToExitCode14(error), output: error instanceof Error ? error.message : String(error) };
35292
+ return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
33659
35293
  }
33660
35294
  }
33661
35295
  async function deleteAlertWithAuthCommand(input2, dependencies) {
@@ -33679,7 +35313,7 @@ async function deleteAlertWithAuthCommand(input2, dependencies) {
33679
35313
  }
33680
35314
 
33681
35315
  // src/slack-commands.ts
33682
- function mapErrorToExitCode15(error) {
35316
+ function mapErrorToExitCode16(error) {
33683
35317
  if (!(error instanceof SlackApiError)) {
33684
35318
  return 1;
33685
35319
  }
@@ -33715,7 +35349,7 @@ async function listSlackDestinationsCommand(input2, api) {
33715
35349
  output: input2.json ? JSON.stringify({ destinations }) : formatSlackDestinationTable(destinations)
33716
35350
  };
33717
35351
  } catch (error) {
33718
- return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
35352
+ return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
33719
35353
  }
33720
35354
  }
33721
35355
  async function listSlackDestinationsWithAuthCommand(input2, dependencies) {
@@ -33744,7 +35378,7 @@ async function getSlackConnectUrlCommand(input2, api) {
33744
35378
  output: input2.json ? JSON.stringify({ install_url: installUrl }) : installUrl
33745
35379
  };
33746
35380
  } catch (error) {
33747
- return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
35381
+ return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
33748
35382
  }
33749
35383
  }
33750
35384
  async function getSlackConnectUrlWithAuthCommand(input2, dependencies) {
@@ -33774,7 +35408,7 @@ async function testSlackDestinationCommand(input2, api) {
33774
35408
  output: input2.json ? JSON.stringify({ delivery }) : `Slack test message delivered for destination: ${input2.destinationId}`
33775
35409
  };
33776
35410
  } catch (error) {
33777
- return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
35411
+ return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
33778
35412
  }
33779
35413
  }
33780
35414
  async function testSlackDestinationWithAuthCommand(input2, dependencies) {
@@ -33804,7 +35438,7 @@ async function deleteSlackDestinationCommand(input2, api) {
33804
35438
  output: input2.json ? JSON.stringify({ destination: deleted }) : `Slack destination deleted: ${deleted.slack_destination_id}`
33805
35439
  };
33806
35440
  } catch (error) {
33807
- return { exitCode: mapErrorToExitCode15(error), output: error instanceof Error ? error.message : String(error) };
35441
+ return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
33808
35442
  }
33809
35443
  }
33810
35444
  async function deleteSlackDestinationWithAuthCommand(input2, dependencies) {
@@ -33824,7 +35458,7 @@ async function deleteSlackDestinationWithAuthCommand(input2, dependencies) {
33824
35458
  }
33825
35459
 
33826
35460
  // src/webhook-commands.ts
33827
- function mapErrorToExitCode16(error) {
35461
+ function mapErrorToExitCode17(error) {
33828
35462
  if (!(error instanceof WebhookApiError)) {
33829
35463
  return 1;
33830
35464
  }
@@ -33869,7 +35503,7 @@ async function listWebhooksCommand(input2, api) {
33869
35503
  output: input2.json ? JSON.stringify({ webhooks }) : formatWebhookTable(webhooks)
33870
35504
  };
33871
35505
  } catch (error) {
33872
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35506
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
33873
35507
  }
33874
35508
  }
33875
35509
  async function listWebhooksWithAuthCommand(input2, dependencies) {
@@ -33917,7 +35551,7 @@ async function createWebhookCommand(input2, api) {
33917
35551
  Signing secret: ${webhook.signing_secret}`
33918
35552
  };
33919
35553
  } catch (error) {
33920
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35554
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
33921
35555
  }
33922
35556
  }
33923
35557
  async function createWebhookWithAuthCommand(input2, dependencies) {
@@ -33971,7 +35605,7 @@ async function updateWebhookCommand(input2, api) {
33971
35605
  output: input2.json ? JSON.stringify({ webhook }) : `Webhook updated: ${webhook.webhook_id}`
33972
35606
  };
33973
35607
  } catch (error) {
33974
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35608
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
33975
35609
  }
33976
35610
  }
33977
35611
  async function updateWebhookWithAuthCommand(input2, dependencies) {
@@ -34017,7 +35651,7 @@ async function deleteWebhookCommand(input2, api) {
34017
35651
  output: input2.json ? JSON.stringify({ webhook }) : `Webhook deleted: ${webhook.webhook_id}`
34018
35652
  };
34019
35653
  } catch (error) {
34020
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35654
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
34021
35655
  }
34022
35656
  }
34023
35657
  async function deleteWebhookWithAuthCommand(input2, dependencies) {
@@ -34055,7 +35689,7 @@ async function testWebhookCommand(input2, api) {
34055
35689
  output: input2.json ? JSON.stringify({ delivery }) : `Webhook test queued: ${delivery.delivery_id} | ${delivery.event_type} | attempts=${delivery.attempt_count}`
34056
35690
  };
34057
35691
  } catch (error) {
34058
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35692
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
34059
35693
  }
34060
35694
  }
34061
35695
  async function testWebhookWithAuthCommand(input2, dependencies) {
@@ -34096,7 +35730,7 @@ async function listWebhookDeliveriesCommand(input2, api) {
34096
35730
  output: input2.json ? JSON.stringify({ deliveries }) : formatWebhookDeliveriesTable(deliveries)
34097
35731
  };
34098
35732
  } catch (error) {
34099
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35733
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
34100
35734
  }
34101
35735
  }
34102
35736
  async function listWebhookDeliveriesWithAuthCommand(input2, dependencies) {
@@ -34134,7 +35768,7 @@ async function retryWebhookDeliveryCommand(input2, api) {
34134
35768
  output: input2.json ? JSON.stringify(result) : `Delivery retried: ${result.delivery_id} | ${result.event_type}`
34135
35769
  };
34136
35770
  } catch (error) {
34137
- return { exitCode: mapErrorToExitCode16(error), output: error instanceof Error ? error.message : String(error) };
35771
+ return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
34138
35772
  }
34139
35773
  }
34140
35774
  async function retryWebhookDeliveryWithAuthCommand(input2, dependencies) {
@@ -34159,7 +35793,7 @@ async function retryWebhookDeliveryWithAuthCommand(input2, dependencies) {
34159
35793
  }
34160
35794
 
34161
35795
  // src/weekly-report-commands.ts
34162
- function mapErrorToExitCode17(error) {
35796
+ function mapErrorToExitCode18(error) {
34163
35797
  if (!(error instanceof WeeklyReportApiError)) {
34164
35798
  return 1;
34165
35799
  }
@@ -34194,7 +35828,7 @@ async function listWeeklyReportChannelsCommand(input2, api) {
34194
35828
  output: input2.json ? JSON.stringify({ channels }) : formatWeeklyReportChannelTable(channels)
34195
35829
  };
34196
35830
  } catch (error) {
34197
- return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
35831
+ return { exitCode: mapErrorToExitCode18(error), output: error instanceof Error ? error.message : String(error) };
34198
35832
  }
34199
35833
  }
34200
35834
  async function listWeeklyReportChannelsWithAuthCommand(input2, dependencies) {
@@ -34227,7 +35861,7 @@ async function createWeeklyReportChannelCommand(input2, api) {
34227
35861
  output: input2.json ? JSON.stringify({ channel }) : `Weekly report channel created: ${channel.channel_id}`
34228
35862
  };
34229
35863
  } catch (error) {
34230
- return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
35864
+ return { exitCode: mapErrorToExitCode18(error), output: error instanceof Error ? error.message : String(error) };
34231
35865
  }
34232
35866
  }
34233
35867
  async function createWeeklyReportChannelWithAuthCommand(input2, dependencies) {
@@ -34262,7 +35896,7 @@ async function updateWeeklyReportChannelCommand(input2, api) {
34262
35896
  output: input2.json ? JSON.stringify({ channel }) : `Weekly report channel updated: ${channel.channel_id}`
34263
35897
  };
34264
35898
  } catch (error) {
34265
- return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
35899
+ return { exitCode: mapErrorToExitCode18(error), output: error instanceof Error ? error.message : String(error) };
34266
35900
  }
34267
35901
  }
34268
35902
  async function updateWeeklyReportChannelWithAuthCommand(input2, dependencies) {
@@ -34293,7 +35927,7 @@ async function deleteWeeklyReportChannelCommand(input2, api) {
34293
35927
  output: input2.json ? JSON.stringify({ channel: deleted }) : `Weekly report channel deleted: ${deleted.channel_id}`
34294
35928
  };
34295
35929
  } catch (error) {
34296
- return { exitCode: mapErrorToExitCode17(error), output: error instanceof Error ? error.message : String(error) };
35930
+ return { exitCode: mapErrorToExitCode18(error), output: error instanceof Error ? error.message : String(error) };
34297
35931
  }
34298
35932
  }
34299
35933
  async function deleteWeeklyReportChannelWithAuthCommand(input2, dependencies) {
@@ -34903,7 +36537,7 @@ async function handleCaptureRuleCommand2(parsedArgv, dependencies) {
34903
36537
  // package.json
34904
36538
  var package_default = {
34905
36539
  name: "@debugbundle/cli",
34906
- version: "1.3.0",
36540
+ version: "1.5.0",
34907
36541
  private: false,
34908
36542
  description: "Command-line interface for DebugBundle",
34909
36543
  license: "AGPL-3.0-only",
@@ -35194,7 +36828,7 @@ ${formatUsage()}`
35194
36828
  return await (dependencies.whoamiCommand ?? whoamiCommand)(appendCommonAuthOptions(parsedArgv, {}));
35195
36829
  }
35196
36830
  if (command === "incidents") {
35197
- expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "source", "project-id", "environment", "service", "status", "severity", "cursor", "limit"]);
36831
+ expectNoUnknownOptions(parsedArgv, ["auth-file", "json", "source", "project-id", "environment", "service", "status", "severity", "first-seen-after", "cursor", "limit"]);
35198
36832
  ensureNoExtraPositionals(parsedArgv, 1);
35199
36833
  const input2 = appendCommonAuthOptions(parsedArgv, {});
35200
36834
  const source = readRetrievalSource(parsedArgv);
@@ -35221,6 +36855,10 @@ ${formatUsage()}`
35221
36855
  if (severity !== void 0) {
35222
36856
  input2.severity = severity;
35223
36857
  }
36858
+ const firstSeenAfter = readStringOption(parsedArgv, "first-seen-after");
36859
+ if (firstSeenAfter !== void 0) {
36860
+ input2.firstSeenAfter = firstSeenAfter;
36861
+ }
35224
36862
  const cursor = readStringOption(parsedArgv, "cursor");
35225
36863
  if (cursor !== void 0) {
35226
36864
  input2.cursor = cursor;
@@ -35377,6 +37015,9 @@ ${formatUsage()}`
35377
37015
  if (command === "probe") {
35378
37016
  return await handleProbeCommand(parsedArgv, dependencies);
35379
37017
  }
37018
+ if (command === "health") {
37019
+ return await handleHealthCommand(parsedArgv, dependencies);
37020
+ }
35380
37021
  if (command === "member") {
35381
37022
  return await handleMemberCommand(parsedArgv, dependencies);
35382
37023
  }