@belvador/mcp 0.5.0 → 0.7.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/cli.js +989 -416
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -182,7 +182,7 @@ function cleanUntrustedText(raw, maxBytes = MCP_LIMITS.untrustedStringMaxBytes)
182
182
  const { text, cut } = cutUtf8(escaped, maxBytes);
183
183
  return { text, cut, suspicious };
184
184
  }
185
- var MCP_TOOLS_VERSION = 5;
185
+ var MCP_TOOLS_VERSION = 6;
186
186
  var MCP_TOOLS = [
187
187
  { name: "get_workspace", toolset: "investigate", scope: "org:read", readOnly: true, destructive: false, idempotent: true },
188
188
  { name: "list_projects", toolset: "investigate", scope: "projects:read", readOnly: true, destructive: false, idempotent: true },
@@ -211,9 +211,7 @@ var MCP_TOOLS = [
211
211
  { name: "search_docs", toolset: "docs", scope: null, readOnly: true, destructive: false, idempotent: true },
212
212
  { name: "get_doc", toolset: "docs", scope: null, readOnly: true, destructive: false, idempotent: true }
213
213
  ];
214
- var MCP_TOOLS_PENDING = {
215
- release_health: "P15"
216
- };
214
+ var MCP_TOOLS_PENDING = {};
217
215
 
218
216
  // ../src/shared/mcp/docs.ts
219
217
  var DOCS_MAX_BYTES = 512 * 1024;
@@ -257,7 +255,7 @@ function docsFetcher(siteUrl, fetcher = fetch, now = () => Date.now()) {
257
255
  import { CLIENT_CAPABILITIES_META_KEY, inputRequired, McpServer } from "@modelcontextprotocol/server";
258
256
 
259
257
  // ../src/shared/contracts/mcp-tools.ts
260
- import { z as z29 } from "zod";
258
+ import { z as z32 } from "zod";
261
259
 
262
260
  // ../src/shared/contracts/api-ops/access.ts
263
261
  import { z as z3 } from "zod";
@@ -1238,7 +1236,7 @@ var TELEMETRY_PLAN_DEFAULTS = {
1238
1236
  // ../src/shared/contracts/vocab/metrics.ts
1239
1237
  var METRIC_TYPES = ["gauge", "sum", "histogram", "exp_histogram"];
1240
1238
  var METRIC_KINDS = ["gauge", "counter", "histogram", "exp_histogram"];
1241
- var METRIC_AGGREGATIONS = ["avg", "sum", "min", "max", "count", "rate", "p50", "p90", "p95", "p99"];
1239
+ var METRIC_AGGREGATIONS = ["avg", "sum", "min", "max", "count", "rate", "p50", "p75", "p90", "p95", "p99"];
1242
1240
  var METRIC_NAME_RE = /^[A-Za-z_][A-Za-z0-9_.:\-/]{0,254}$/;
1243
1241
  var METRIC_ATTR_KEY_RE = /^[A-Za-z0-9_.:\-/@]{1,256}$/;
1244
1242
  var METRIC_GROUP_BY_MAX = 2;
@@ -2182,6 +2180,48 @@ import { z as z16 } from "zod";
2182
2180
 
2183
2181
  // ../src/shared/contracts/signed-message.ts
2184
2182
  import { z as z15 } from "zod";
2183
+
2184
+ // ../src/shared/contracts/limits.ts
2185
+ var INGEST_LIMITS = {
2186
+ envelopeCompressedMaxBytes: 20 * 1024 * 1024,
2187
+ decompressedMaxBytes: 200 * 1024 * 1024,
2188
+ maxCompressionRatio: 50,
2189
+ eventItemMaxBytes: 1024 * 1024,
2190
+ attachmentMaxBytes: 5 * 1024 * 1024,
2191
+ jsonMaxDepth: 20,
2192
+ jsonMaxKeysPerObject: 1000,
2193
+ jsonMaxKeysTotal: 1e4,
2194
+ jsonHardMaxDepth: 128,
2195
+ stringMaxChars: 8192,
2196
+ framesMaxPerException: 250,
2197
+ exceptionsMax: 10,
2198
+ breadcrumbsMax: 100,
2199
+ tagsMax: 20,
2200
+ tagKeyMaxChars: 32,
2201
+ tagValueMaxChars: 200,
2202
+ sourceMapMaxBytes: 10 * 1024 * 1024,
2203
+ sourceMapSegmentMaxChars: 1024,
2204
+ envelopeItemsMax: 100
2205
+ };
2206
+ var BUFFER_LIMITS = {
2207
+ queueInlineMaxBytes: 100 * 1024,
2208
+ maxAgeDays: 14,
2209
+ nodeMaxBytes: 8 * 1024 ** 3,
2210
+ alertRatio: 0.8,
2211
+ alertInflowPerSecond: 5000
2212
+ };
2213
+ var RELAY_LIMITS = {
2214
+ chunkBytes: 512 * 1024,
2215
+ maxInflightMessages: 4,
2216
+ maxInflightBytes: 24 * 1024 * 1024,
2217
+ clockSkewSeconds: 60,
2218
+ nonceMemorySeconds: 600,
2219
+ ackTimeoutMs: 2000,
2220
+ heartbeatSeconds: 30,
2221
+ reconnectMaxSeconds: 30
2222
+ };
2223
+
2224
+ // ../src/shared/contracts/signed-message.ts
2185
2225
  var nodeIdSchema = z15.guid();
2186
2226
  var signedEnvelopeSchema = z15.object({
2187
2227
  node_id: nodeIdSchema,
@@ -3089,154 +3129,504 @@ var MONITOR_OPERATIONS = [
3089
3129
  ];
3090
3130
 
3091
3131
  // ../src/shared/contracts/api-ops/node-data.ts
3132
+ import { z as z23 } from "zod";
3133
+
3134
+ // ../src/shared/contracts/release-health.ts
3135
+ import { z as z21 } from "zod";
3136
+
3137
+ // ../src/shared/contracts/sourcemaps.ts
3092
3138
  import { z as z20 } from "zod";
3093
- var issueId = z20.number().int().positive();
3094
- var csv = z20.string().min(1).max(2000);
3095
- var name2 = z20.string().min(1).max(256);
3096
- var period = z20.enum(["1h", "24h", "7d", "14d", "30d"]);
3097
- var nodeCursor = z20.string().min(1).max(600).optional();
3139
+ var UPLOAD_LIMITS = {
3140
+ requestMaxBytes: RELAY_LIMITS.maxInflightBytes - 512 * 1024,
3141
+ tarMaxBytes: 64 * 1024 * 1024,
3142
+ fileMaxBytes: INGEST_LIMITS.sourceMapMaxBytes,
3143
+ filesMax: 1000,
3144
+ requestsPerHour: 60,
3145
+ retentionDays: 90
3146
+ };
3147
+ var UPLOAD_SCOPES = ["sourcemaps:write", "releases:write"];
3148
+ var UPLOAD_TOKEN_PATTERN = /^blv_sm_[A-Za-z0-9_-]{43}$/;
3149
+ var tokenHashSchema = z20.string().regex(/^[a-f0-9]{64}$/);
3150
+ var uploadTokenConfigSchema = z20.object({
3151
+ v: z20.literal(1),
3152
+ project_id: z20.number().int().positive(),
3153
+ project_public_id: z20.number().int().positive(),
3154
+ node_id: nodeIdSchema,
3155
+ workspace_id: z20.guid(),
3156
+ scopes: z20.array(z20.enum(UPLOAD_SCOPES)).min(1).max(4),
3157
+ expires_at: z20.string().datetime(),
3158
+ is_active: z20.boolean()
3159
+ });
3160
+ var releaseNameSchema = z20.string().min(1).max(200).regex(/^[^\s/\\\u0000-\u001f\u007f]+$/);
3161
+ var SENTRY_COMPAT = {
3162
+ apiRoot: "/api/0",
3163
+ chunkSize: 2 * 1024 * 1024,
3164
+ chunksPerRequest: 3,
3165
+ maxRequestSize: 7 * 1024 * 1024,
3166
+ maxFileSize: 64 * 1024 * 1024,
3167
+ maxBundleEntries: 4000,
3168
+ concurrency: 1,
3169
+ maxWaitSeconds: 60,
3170
+ chunkBytesPerHour: 1024 * 1024 * 1024,
3171
+ pendingBytesPerProject: 128 * 1024 * 1024,
3172
+ pendingTtlMs: 60 * 60 * 1000
3173
+ };
3174
+ var sha1HexSchema = z20.string().regex(/^[0-9a-f]{40}$/);
3175
+ var assembleRequestSchema = z20.object({
3176
+ checksum: sha1HexSchema,
3177
+ chunks: z20.array(sha1HexSchema).max(Math.ceil(SENTRY_COMPAT.maxFileSize / SENTRY_COMPAT.chunkSize)),
3178
+ projects: z20.array(z20.string().max(200)).max(50).optional(),
3179
+ version: releaseNameSchema.optional(),
3180
+ dist: z20.string().max(64).regex(/^[A-Za-z0-9._-]*$/).optional()
3181
+ });
3182
+ var assembleResponseSchema = z20.object({
3183
+ state: z20.enum(["ok", "created", "assembling", "not_found", "error"]),
3184
+ missingChunks: z20.array(sha1HexSchema),
3185
+ detail: z20.string().max(200).nullable()
3186
+ });
3187
+ var uploadHeaderSchema = z20.object({
3188
+ id: z20.string().regex(/^[A-Za-z0-9_-]{8,64}$/),
3189
+ project_id: z20.number().int().positive(),
3190
+ release: releaseNameSchema.optional(),
3191
+ dist: z20.string().max(64).regex(/^[A-Za-z0-9._-]*$/).optional(),
3192
+ token: z20.string().regex(UPLOAD_TOKEN_PATTERN),
3193
+ content_encoding: z20.enum(["identity", "gzip"]),
3194
+ op: z20.enum(["tar", "chunks", "assemble", "release"]).optional(),
3195
+ chunks: z20.array(z20.object({
3196
+ sha1: sha1HexSchema,
3197
+ size: z20.number().int().positive().max(SENTRY_COMPAT.chunkSize)
3198
+ })).max(SENTRY_COMPAT.chunksPerRequest).optional()
3199
+ });
3200
+ var uploadResultSchema = z20.object({
3201
+ accepted: z20.array(z20.object({ file: z20.string().max(200), debug_id: z20.guid(), size: z20.number().int() })).max(UPLOAD_LIMITS.filesMax),
3202
+ skipped: z20.array(z20.object({
3203
+ file: z20.string().max(200),
3204
+ reason: z20.enum([
3205
+ "not_a_map",
3206
+ "no_debug_id",
3207
+ "too_large",
3208
+ "invalid_json",
3209
+ "unsupported",
3210
+ "bad_name"
3211
+ ])
3212
+ })).max(UPLOAD_LIMITS.filesMax)
3213
+ });
3214
+
3215
+ // ../src/shared/contracts/release-health.ts
3216
+ var RELEASE_HEALTH = {
3217
+ verifyHours: 24,
3218
+ windowHours: 24,
3219
+ increaseFactor: 2,
3220
+ increaseMinEvents: 10,
3221
+ listMax: 50,
3222
+ candidatesMax: 500,
3223
+ releasesMax: 50,
3224
+ commitsMax: 1000,
3225
+ deploysMax: 50,
3226
+ memoryReleasesMax: 5000,
3227
+ memoryDeploysMax: 1e4,
3228
+ requestsPerHour: 600,
3229
+ bodyMaxBytes: 4 * 1024 * 1024,
3230
+ fixLookbackDays: 30
3231
+ };
3232
+ var FIX_STATUSES = ["fixed", "not_fixed", "unverified", "unknown"];
3233
+ var FIX_REASONS = [
3234
+ "verified",
3235
+ "event_in_release",
3236
+ "regressed",
3237
+ "order_unknown",
3238
+ "not_deployed",
3239
+ "no_deploy_marker",
3240
+ "not_running",
3241
+ "too_early"
3242
+ ];
3243
+ var RESOLUTION_MODES = ["now", "next_release", "in_release"];
3244
+ var RELEASE_SOURCES = ["cli", "api", "sdk"];
3245
+ var environmentNameSchema = z21.string().trim().regex(ENVIRONMENT_RE).refine((v) => !/[\s/]/.test(v));
3246
+ var isoTime = z21.string().datetime({ offset: true });
3247
+ var httpUrl = z21.string().max(500).refine((v) => /^https?:\/\/[^\s]+$/i.test(v), "http(s) URL");
3248
+ var DEPLOY_ID_RE = /^[A-Za-z0-9_.:-]{1,64}$/;
3249
+ var commitShaSchema = z21.string().regex(/^[0-9A-Za-z._-]{4,64}$/);
3250
+ var repoNameSchema = z21.string().min(1).max(200).regex(/^[^\u0000-\u001f\u007f]+$/);
3251
+ var deploymentInputSchema = z21.object({
3252
+ version: releaseNameSchema,
3253
+ environment: environmentNameSchema,
3254
+ name: z21.string().trim().min(1).max(200).optional(),
3255
+ url: httpUrl.optional(),
3256
+ started_at: isoTime.optional(),
3257
+ finished_at: isoTime.optional(),
3258
+ deploy_id: z21.string().regex(DEPLOY_ID_RE).optional()
3259
+ });
3260
+ var commitSchema = z21.object({ sha: commitShaSchema, repo: repoNameSchema.optional() });
3261
+ var releaseRelaySchema = z21.discriminatedUnion("action", [
3262
+ z21.object({
3263
+ action: z21.literal("create"),
3264
+ version: releaseNameSchema,
3265
+ date_released: isoTime.optional(),
3266
+ commits: z21.array(commitSchema).max(RELEASE_HEALTH.commitsMax).optional()
3267
+ }),
3268
+ z21.object({
3269
+ action: z21.literal("update"),
3270
+ version: releaseNameSchema,
3271
+ date_released: isoTime.optional(),
3272
+ commits: z21.array(commitSchema).max(RELEASE_HEALTH.commitsMax).optional()
3273
+ }),
3274
+ z21.object({ action: z21.literal("get"), version: releaseNameSchema }),
3275
+ z21.object({ action: z21.literal("list") }),
3276
+ z21.object({ action: z21.literal("previous"), version: releaseNameSchema }),
3277
+ z21.object({ action: z21.literal("deploy"), deploy: deploymentInputSchema }),
3278
+ z21.object({ action: z21.literal("deploys"), version: releaseNameSchema })
3279
+ ]);
3280
+ var cliCommit = z21.object({ id: z21.string().max(200), repository: z21.string().max(400).nullish() }).passthrough();
3281
+ var cliRef = z21.object({
3282
+ repository: z21.string().max(400),
3283
+ commit: z21.string().max(200),
3284
+ previousCommit: z21.string().max(200).nullish()
3285
+ }).passthrough();
3286
+ var cliReleaseCreateSchema = z21.object({
3287
+ version: releaseNameSchema,
3288
+ projects: z21.array(z21.string().max(200)).max(50).optional(),
3289
+ dateReleased: isoTime.nullish(),
3290
+ dateStarted: isoTime.nullish(),
3291
+ refs: z21.array(cliRef).max(100).optional(),
3292
+ commits: z21.array(cliCommit).max(1e4).optional()
3293
+ }).passthrough();
3294
+ var cliReleaseUpdateSchema = cliReleaseCreateSchema.omit({ version: true }).extend({ version: releaseNameSchema.optional() });
3295
+ var cliDeployCreateSchema = z21.object({
3296
+ environment: z21.string().max(64),
3297
+ name: z21.string().max(200).nullish(),
3298
+ url: z21.string().max(500).nullish(),
3299
+ dateStarted: isoTime.nullish(),
3300
+ dateFinished: isoTime.nullish()
3301
+ }).passthrough();
3302
+ var iso5 = z21.string();
3303
+ var releaseRowSchema = z21.object({
3304
+ version: z21.string(),
3305
+ source: z21.enum(RELEASE_SOURCES),
3306
+ environment: z21.string().nullable(),
3307
+ created_at: iso5.nullable(),
3308
+ date_released: iso5.nullable(),
3309
+ deployed_at: iso5.nullable(),
3310
+ last_deploy_at: iso5.nullable(),
3311
+ deploys: z21.number().int(),
3312
+ first_seen: iso5.nullable(),
3313
+ last_seen: iso5.nullable(),
3314
+ commit_count: z21.number().int(),
3315
+ events: z21.number().int(),
3316
+ events_per_hour: z21.number(),
3317
+ previous: z21.string().nullable(),
3318
+ previous_events_per_hour: z21.number().nullable(),
3319
+ new_issues: z21.number().int(),
3320
+ regressed_issues: z21.number().int(),
3321
+ increased_issues: z21.number().int()
3322
+ });
3323
+ var releaseListSchema = z21.object({
3324
+ releases: z21.array(releaseRowSchema),
3325
+ environments: z21.array(z21.string()),
3326
+ environment: z21.string().nullable(),
3327
+ has_deploy_markers: z21.boolean()
3328
+ });
3329
+ var healthIssueSchema = z21.object({
3330
+ issue_id: z21.number().int(),
3331
+ short_id: z21.string(),
3332
+ title: z21.string(),
3333
+ culprit: z21.string(),
3334
+ level: z21.string(),
3335
+ status: z21.string(),
3336
+ events: z21.number().int(),
3337
+ previous_events: z21.number().int(),
3338
+ first_seen: iso5.nullable(),
3339
+ sparkline: z21.array(z21.number().int())
3340
+ });
3341
+ var deploymentRowSchema = z21.object({
3342
+ deploy_id: z21.string(),
3343
+ version: z21.string(),
3344
+ environment: z21.string(),
3345
+ name: z21.string().nullable(),
3346
+ url: z21.string().nullable(),
3347
+ started_at: iso5,
3348
+ finished_at: iso5,
3349
+ source: z21.enum(RELEASE_SOURCES)
3350
+ });
3351
+ var releaseHealthSchema = z21.object({
3352
+ release: releaseRowSchema,
3353
+ compare: z21.string().nullable(),
3354
+ window: z21.object({
3355
+ start: iso5.nullable(),
3356
+ end: iso5.nullable(),
3357
+ hours: z21.number(),
3358
+ from_deploy: z21.boolean()
3359
+ }),
3360
+ new: z21.array(healthIssueSchema),
3361
+ regressed: z21.array(healthIssueSchema),
3362
+ increased: z21.array(healthIssueSchema),
3363
+ deploys: z21.array(deploymentRowSchema),
3364
+ commits: z21.array(commitSchema),
3365
+ truncated: z21.boolean()
3366
+ });
3367
+ var fixEnvSchema = z21.object({
3368
+ environment: z21.string(),
3369
+ status: z21.enum(FIX_STATUSES),
3370
+ reason: z21.enum(FIX_REASONS),
3371
+ target: z21.string().nullable(),
3372
+ target_deployed_at: iso5.nullable(),
3373
+ release: z21.string().nullable(),
3374
+ first_seen: iso5.nullable(),
3375
+ observed_hours: z21.number().nullable()
3376
+ });
3377
+ var fixStatusSchema = z21.object({
3378
+ issue_id: z21.number().int(),
3379
+ resolution: z21.object({
3380
+ mode: z21.enum(RESOLUTION_MODES),
3381
+ resolved_at: iso5,
3382
+ release: z21.string().nullable(),
3383
+ regressed: z21.boolean()
3384
+ }).nullable(),
3385
+ status: z21.enum(FIX_STATUSES).nullable(),
3386
+ environments: z21.array(fixEnvSchema),
3387
+ verify_hours: z21.number()
3388
+ });
3389
+
3390
+ // ../src/shared/contracts/web-vitals.ts
3391
+ import { z as z22 } from "zod";
3392
+
3393
+ // ../src/shared/contracts/vocab/web-vitals.ts
3394
+ var WEB_VITAL_NAMES = ["LCP", "INP", "CLS", "FCP", "TTFB"];
3395
+ var WEB_VITAL_RATINGS = ["good", "needs-improvement", "poor"];
3396
+ var WEB_VITAL_PATH_MAX_CHARS = 200;
3397
+
3398
+ // ../src/shared/contracts/web-vitals.ts
3399
+ var WEB_VITAL_LIMITS = {
3400
+ routesMax: 200,
3401
+ routesShown: 20,
3402
+ attributionShown: 10,
3403
+ estimateBelow: 100,
3404
+ defaultSampleRate: 0.1,
3405
+ targetMaxChars: 100,
3406
+ pathMaxChars: WEB_VITAL_PATH_MAX_CHARS,
3407
+ maxWindowMs: 7 * 24 * 3600 * 1000,
3408
+ defaultWindowMs: 24 * 3600 * 1000
3409
+ };
3410
+ var ratingCounts = z22.object({
3411
+ good: z22.number().int().nonnegative(),
3412
+ needs_improvement: z22.number().int().nonnegative(),
3413
+ poor: z22.number().int().nonnegative()
3414
+ });
3415
+ var webVitalSummarySchema = z22.object({
3416
+ name: z22.enum(WEB_VITAL_NAMES),
3417
+ metric: z22.string(),
3418
+ unit: z22.enum(["ms", "1"]),
3419
+ samples: z22.number().int().nonnegative(),
3420
+ p75: z22.number().nullable(),
3421
+ rating: z22.enum(WEB_VITAL_RATINGS).nullable(),
3422
+ estimate: z22.boolean(),
3423
+ ratings: ratingCounts,
3424
+ distribution: z22.array(z22.object({ le: z22.number().nullable(), count: z22.number().int().nonnegative() })),
3425
+ routes: z22.array(z22.object({
3426
+ path: z22.string(),
3427
+ samples: z22.number().int().nonnegative(),
3428
+ p75: z22.number().nullable(),
3429
+ rating: z22.enum(WEB_VITAL_RATINGS).nullable()
3430
+ })),
3431
+ routes_total: z22.number().int().nonnegative(),
3432
+ attribution: z22.array(z22.object({ target: z22.string(), samples: z22.number().int().nonnegative(), p75: z22.number().nullable() }))
3433
+ });
3434
+ var webVitalsSummarySchema = z22.object({
3435
+ from: z22.string(),
3436
+ to: z22.string(),
3437
+ path: z22.string().nullable(),
3438
+ vitals: z22.array(webVitalSummarySchema),
3439
+ complete: z22.boolean()
3440
+ });
3441
+
3442
+ // ../src/shared/contracts/api-ops/node-data.ts
3443
+ var issueId = z23.number().int().positive();
3444
+ var csv = z23.string().min(1).max(2000);
3445
+ var projectIds2 = z23.string().max(2000).regex(/^[1-9][0-9]{0,15}(?:,[1-9][0-9]{0,15}){0,99}$/, "comma-separated project ids");
3446
+ var name2 = z23.string().min(1).max(256);
3447
+ var period = z23.enum(["1h", "24h", "7d", "14d", "30d"]);
3448
+ var nodeCursor = z23.string().min(1).max(600).optional();
3098
3449
  var windowFields = {
3099
- start: z20.string().max(40).optional(),
3100
- end: z20.string().max(40).optional()
3450
+ start: z23.string().max(40).optional(),
3451
+ end: z23.string().max(40).optional()
3101
3452
  };
3102
- var traceId = z20.string().regex(/^[0-9a-fA-F]{32}$/);
3103
- var spanId = z20.string().regex(/^[0-9a-fA-F]{16}$/);
3104
- var attrs = z20.string().max(2000).optional();
3453
+ var traceId = z23.string().regex(/^[0-9a-fA-F]{32}$/);
3454
+ var spanId = z23.string().regex(/^[0-9a-fA-F]{16}$/);
3455
+ var attrs = z23.string().max(2000).optional();
3105
3456
  var telemetryCommon = {
3106
3457
  ...windowFields,
3107
- project: csv.optional(),
3458
+ project: projectIds2.optional(),
3108
3459
  environment: csv.optional(),
3109
3460
  service: csv.optional(),
3110
3461
  attrs
3111
3462
  };
3112
- var issueChange = z20.union([
3113
- z20.object({ action: z20.literal("resolve"), inNextRelease: z20.boolean().optional() }),
3114
- z20.object({ action: z20.literal("unresolve") }),
3115
- z20.object({ action: z20.literal("archive"), mode: z20.enum(["until_escalating", "forever"]) }),
3116
- z20.object({
3117
- action: z20.literal("archive"),
3118
- mode: z20.literal("until_condition"),
3119
- events: z20.number().int().min(1).max(1e6).optional(),
3120
- users: z20.number().int().min(1).max(1e5).optional(),
3121
- until: z20.string().datetime().optional()
3122
- }),
3123
- z20.object({ action: z20.literal("assign"), userId: z20.guid().nullable() }),
3124
- z20.object({ action: z20.literal("priority"), priority: z20.enum(["low", "medium", "high"]) })
3463
+ var issueChange = z23.union([
3464
+ z23.object({
3465
+ action: z23.literal("resolve"),
3466
+ inNextRelease: z23.boolean().optional(),
3467
+ inRelease: releaseNameSchema.optional()
3468
+ }),
3469
+ z23.object({ action: z23.literal("unresolve") }),
3470
+ z23.object({ action: z23.literal("archive"), mode: z23.enum(["until_escalating", "forever"]) }),
3471
+ z23.object({
3472
+ action: z23.literal("archive"),
3473
+ mode: z23.literal("until_condition"),
3474
+ events: z23.number().int().min(1).max(1e6).optional(),
3475
+ users: z23.number().int().min(1).max(1e5).optional(),
3476
+ until: z23.string().datetime().optional()
3477
+ }),
3478
+ z23.object({ action: z23.literal("assign"), userId: z23.guid().nullable() }),
3479
+ z23.object({ action: z23.literal("priority"), priority: z23.enum(["low", "medium", "high"]) })
3125
3480
  ]);
3126
3481
  var NODE_INPUTS = {
3127
- issuesList: z20.object({
3128
- project: csv.optional(),
3129
- status: z20.enum(["unresolved", "resolved", "archived", "all"]).optional(),
3482
+ issuesList: z23.object({
3483
+ project: projectIds2.optional(),
3484
+ status: z23.enum(["unresolved", "resolved", "archived", "all"]).optional(),
3130
3485
  level: csv.optional(),
3131
3486
  priority: csv.optional(),
3132
3487
  environment: csv.optional(),
3133
3488
  release: csv.optional(),
3134
- assignee: z20.string().max(64).optional(),
3489
+ assignee: z23.string().max(64).optional(),
3135
3490
  period: period.optional(),
3136
- q: z20.string().max(200).optional(),
3137
- sort: z20.enum(["last_seen", "first_seen", "events", "users", "priority"]).optional(),
3491
+ q: z23.string().max(200).optional(),
3492
+ sort: z23.enum(["last_seen", "first_seen", "events", "users", "priority"]).optional(),
3138
3493
  cursor: nodeCursor,
3139
- limit: z20.number().int().min(1).max(100).optional()
3494
+ limit: z23.number().int().min(1).max(100).optional()
3140
3495
  }),
3141
- issue: z20.object({ issueId }),
3142
- issueStats: z20.object({ issueId, range: z20.enum(["24h", "30d"]).optional() }),
3143
- issueEvents: z20.object({ issueId, cursor: nodeCursor }),
3144
- issueEvent: z20.object({
3496
+ issue: z23.object({ issueId }),
3497
+ issueStats: z23.object({ issueId, range: z23.enum(["24h", "30d"]).optional() }),
3498
+ issueEvents: z23.object({ issueId, cursor: nodeCursor }),
3499
+ issueEvent: z23.object({
3145
3500
  issueId,
3146
- eventId: z20.string().regex(/^([0-9a-f]{32}|latest|oldest)$/)
3501
+ eventId: z23.string().regex(/^([0-9a-f]{32}|latest|oldest)$/)
3147
3502
  }),
3148
- issueUpdate: z20.object({ issueId, change: issueChange }),
3149
- issuesBulk: z20.object({
3150
- issueIds: z20.array(issueId).min(1).max(100),
3503
+ issueUpdate: z23.object({ issueId, change: issueChange }),
3504
+ issuesBulk: z23.object({
3505
+ issueIds: z23.array(issueId).min(1).max(100),
3151
3506
  action: issueChange
3152
3507
  }),
3153
- spansList: z20.object({
3508
+ spansList: z23.object({
3154
3509
  ...telemetryCommon,
3155
- operation: z20.string().min(1).max(1024).optional(),
3156
- status: z20.enum(["unset", "ok", "error"]).optional(),
3157
- kind: z20.enum(["internal", "server", "client", "producer", "consumer"]).optional(),
3158
- minDurationMs: z20.number().min(0).max(86400000).optional(),
3159
- maxDurationMs: z20.number().min(0).max(86400000).optional(),
3160
- mode: z20.enum(["spans", "traces"]).optional(),
3510
+ operation: z23.string().min(1).max(1024).optional(),
3511
+ status: z23.enum(["unset", "ok", "error"]).optional(),
3512
+ kind: z23.enum(["internal", "server", "client", "producer", "consumer"]).optional(),
3513
+ minDurationMs: z23.number().min(0).max(86400000).optional(),
3514
+ maxDurationMs: z23.number().min(0).max(86400000).optional(),
3515
+ mode: z23.enum(["spans", "traces"]).optional(),
3161
3516
  cursor: nodeCursor
3162
3517
  }),
3163
- spansHistogram: z20.object({
3518
+ spansHistogram: z23.object({
3164
3519
  ...telemetryCommon,
3165
- operation: z20.string().min(1).max(1024).optional(),
3166
- status: z20.enum(["unset", "ok", "error"]).optional()
3520
+ operation: z23.string().min(1).max(1024).optional(),
3521
+ status: z23.enum(["unset", "ok", "error"]).optional()
3167
3522
  }),
3168
- trace: z20.object({ traceId }),
3169
- traceSpans: z20.object({ traceId, errorsOnly: z20.enum(["1"]).optional(), ...windowFields }),
3170
- span: z20.object({ traceId, spanId, ...windowFields }),
3171
- logsList: z20.object({
3523
+ trace: z23.object({ traceId }),
3524
+ traceSpans: z23.object({ traceId, errorsOnly: z23.enum(["1"]).optional(), ...windowFields }),
3525
+ span: z23.object({ traceId, spanId, ...windowFields }),
3526
+ logsList: z23.object({
3172
3527
  ...telemetryCommon,
3173
- severityMin: z20.enum(["trace", "debug", "info", "warn", "error", "fatal"]).optional(),
3528
+ severityMin: z23.enum(["trace", "debug", "info", "warn", "error", "fatal"]).optional(),
3174
3529
  traceId: traceId.optional(),
3175
3530
  spanId: spanId.optional(),
3176
- q: z20.string().max(500).optional(),
3177
- order: z20.enum(["asc", "desc"]).optional(),
3531
+ q: z23.string().max(500).optional(),
3532
+ order: z23.enum(["asc", "desc"]).optional(),
3178
3533
  cursor: nodeCursor
3179
3534
  }),
3180
- logsFacets: z20.object({
3535
+ logsFacets: z23.object({
3181
3536
  ...telemetryCommon,
3182
- severityMin: z20.enum(["trace", "debug", "info", "warn", "error", "fatal"]).optional(),
3183
- q: z20.string().max(500).optional()
3184
- }),
3185
- logAround: z20.object({
3186
- logId: name2,
3187
- at: z20.string().max(40),
3188
- same: z20.enum(["service", "trace"]).optional(),
3189
- before: z20.number().int().min(0).max(200).optional(),
3190
- after: z20.number().int().min(0).max(200).optional()
3191
- }),
3192
- metricsNames: z20.object({
3193
- project: z20.number().int().positive(),
3537
+ severityMin: z23.enum(["trace", "debug", "info", "warn", "error", "fatal"]).optional(),
3538
+ q: z23.string().max(500).optional()
3539
+ }),
3540
+ logAround: z23.object({
3541
+ logId: z23.guid(),
3542
+ at: z23.string().max(40),
3543
+ same: z23.enum(["service", "trace"]).optional(),
3544
+ before: z23.number().int().min(0).max(200).optional(),
3545
+ after: z23.number().int().min(0).max(200).optional()
3546
+ }),
3547
+ metricsNames: z23.object({
3548
+ project: z23.number().int().positive(),
3194
3549
  environment: csv.optional(),
3195
- q: z20.string().max(255).optional()
3550
+ q: z23.string().max(255).optional()
3196
3551
  }),
3197
- metricsSeries: z20.object({
3198
- project: z20.number().int().positive(),
3199
- name: z20.string().regex(METRIC_NAME_RE),
3552
+ metricsSeries: z23.object({
3553
+ project: z23.number().int().positive(),
3554
+ name: z23.string().regex(METRIC_NAME_RE),
3200
3555
  environment: csv.optional(),
3201
3556
  attrs,
3202
- cursor: z20.string().regex(/^[0-9a-f]{16}$/).optional()
3557
+ cursor: z23.string().regex(/^[0-9a-f]{16}$/).optional()
3203
3558
  }),
3204
- metricsQuery: z20.object({
3205
- project: z20.number().int().positive(),
3206
- name: z20.string().regex(METRIC_NAME_RE),
3207
- aggregation: z20.enum(METRIC_AGGREGATIONS),
3559
+ metricsQuery: z23.object({
3560
+ project: z23.number().int().positive(),
3561
+ name: z23.string().regex(METRIC_NAME_RE),
3562
+ aggregation: z23.enum(METRIC_AGGREGATIONS),
3208
3563
  ...windowFields,
3209
- step: z20.number().int().min(METRIC_QUERY.minStepSeconds).max(METRIC_QUERY.maxStepSeconds).multipleOf(60).optional(),
3564
+ step: z23.number().int().min(METRIC_QUERY.minStepSeconds).max(METRIC_QUERY.maxStepSeconds).multipleOf(60).optional(),
3210
3565
  attrs,
3211
- groupBy: z20.string().min(1).max(600).optional(),
3566
+ groupBy: z23.string().min(1).max(600).optional(),
3212
3567
  environment: csv.optional()
3213
3568
  }),
3214
- telemetryUsage: z20.object({ project: csv.optional(), days: z20.number().int().min(1).max(31).optional() }),
3215
- monitorSignal: z20.object({ monitorId: z20.guid(), hours: z20.number().int().min(1).max(24).optional() }),
3216
- monitorOccurrences: z20.object({
3217
- monitorId: z20.guid(),
3218
- state: z20.enum(["open", "finished", "all"]).optional(),
3219
- environment: z20.string().min(1).max(64).optional(),
3569
+ telemetryUsage: z23.object({
3570
+ project: projectIds2.optional(),
3571
+ days: z23.number().int().min(1).max(31).optional()
3572
+ }),
3573
+ monitorSignal: z23.object({
3574
+ monitorId: z23.guid(),
3575
+ hours: z23.number().int().min(1).max(24).optional()
3576
+ }),
3577
+ monitorOccurrences: z23.object({
3578
+ monitorId: z23.guid(),
3579
+ state: z23.enum(["open", "finished", "all"]).optional(),
3580
+ environment: z23.string().min(1).max(64).optional(),
3220
3581
  cursor: nodeCursor
3221
3582
  }),
3222
- monitorBacktest: z20.object({ project: z20.number().int().positive(), settings: backtestSettingsSchema }),
3223
- occurrenceCreate: z20.object({
3224
- project: z20.number().int().positive(),
3583
+ monitorBacktest: z23.object({
3584
+ project: z23.number().int().positive(),
3585
+ settings: backtestSettingsSchema
3586
+ }),
3587
+ occurrenceCreate: z23.object({
3588
+ project: z23.number().int().positive(),
3225
3589
  monitorSlug: occurrenceInputSchema.shape.monitor_slug,
3226
3590
  occurrenceId: occurrenceInputSchema.shape.occurrence_id,
3227
3591
  dueAt: occurrenceInputSchema.shape.due_at,
3228
3592
  environment: occurrenceInputSchema.shape.environment
3229
3593
  }),
3230
- occurrenceCancel: z20.object({
3231
- project: z20.number().int().positive(),
3232
- monitorSlug: z20.string().regex(SLUG_RE),
3233
- occurrenceId: z20.string().regex(OCCURRENCE_ID_RE),
3234
- environment: z20.string().min(1).max(64).optional()
3594
+ occurrenceCancel: z23.object({
3595
+ project: z23.number().int().positive(),
3596
+ monitorSlug: z23.string().regex(SLUG_RE),
3597
+ occurrenceId: z23.string().regex(OCCURRENCE_ID_RE),
3598
+ environment: z23.string().min(1).max(64).optional()
3235
3599
  }),
3236
- ticket: z20.object({
3237
- scope: z20.enum(["read", "write"]).default("read"),
3238
- project: z20.number().int().positive().optional(),
3239
- environment: z20.string().min(1).max(64).optional()
3600
+ webVitals: z23.object({
3601
+ project: z23.number().int().positive(),
3602
+ ...windowFields,
3603
+ environment: csv.optional(),
3604
+ path: z23.string().max(WEB_VITAL_LIMITS.pathMaxChars).regex(/^(?:\/[^\s?#]*|other)$/).optional()
3605
+ }),
3606
+ releasesList: z23.object({
3607
+ project: z23.number().int().positive(),
3608
+ environment: environmentNameSchema.optional()
3609
+ }),
3610
+ releaseHealth: z23.object({
3611
+ project: z23.number().int().positive(),
3612
+ version: releaseNameSchema,
3613
+ environment: environmentNameSchema.optional(),
3614
+ compare: releaseNameSchema.optional()
3615
+ }),
3616
+ deploymentCreate: z23.object({
3617
+ project: z23.number().int().positive(),
3618
+ version: deploymentInputSchema.shape.version,
3619
+ environment: deploymentInputSchema.shape.environment,
3620
+ name: deploymentInputSchema.shape.name,
3621
+ url: deploymentInputSchema.shape.url,
3622
+ startedAt: deploymentInputSchema.shape.started_at,
3623
+ finishedAt: deploymentInputSchema.shape.finished_at,
3624
+ deployId: deploymentInputSchema.shape.deploy_id
3625
+ }),
3626
+ ticket: z23.object({
3627
+ scope: z23.enum(["read", "write"]).default("read"),
3628
+ project: z23.number().int().positive().optional(),
3629
+ environment: z23.string().min(1).max(64).optional()
3240
3630
  })
3241
3631
  };
3242
3632
  var N = NODE_INPUTS;
@@ -3424,7 +3814,54 @@ var NODE_OPERATIONS = [
3424
3814
  scope: "metrics:read",
3425
3815
  input: N.metricsQuery,
3426
3816
  node: { path: "q/metrics/query", window: true },
3427
- summary: "One metric aggregated per step (avg, sum, min, max, count, rate, p50–p99) in a window of at most 7 days, optionally grouped by up to two attributes (≤ 50 groups, ≤ 10,000 points), with exemplar trace ids."
3817
+ summary: "One metric aggregated per step (avg, sum, min, max, count, rate, p50, p75, p90, p95, p99) in a window of at most 7 days, optionally grouped by up to two attributes (≤ 50 groups, ≤ 10,000 points), with exemplar trace ids."
3818
+ }),
3819
+ op({
3820
+ ...read,
3821
+ id: "metrics.web_vitals",
3822
+ path: "/v1/projects/{project}/web-vitals",
3823
+ scope: "metrics:read",
3824
+ input: N.webVitals,
3825
+ node: { path: "q/metrics/web-vitals", window: true },
3826
+ summary: "Core Web Vitals of real users (LCP, INP, CLS, FCP, TTFB) in a window of at most 7 days: samples, p75 with its web.dev rating, samples per rating, the distribution, the busiest routes and the elements behind slow samples. Optionally one route. Needs browser SDK `webVitals` and node agent 0.1.40."
3827
+ }),
3828
+ op({
3829
+ ...read,
3830
+ id: "releases.list",
3831
+ path: "/v1/projects/{project}/releases",
3832
+ scope: "releases:read",
3833
+ input: N.releasesList,
3834
+ node: { path: "q/releases" },
3835
+ summary: "Releases of one project in one environment, newest first by deploy order (else version order): first and last deploy, events, issues, and the counts of new, regressed and increased issues in each release's first 24 hours."
3836
+ }),
3837
+ op({
3838
+ ...read,
3839
+ id: "releases.health",
3840
+ path: "/v1/projects/{project}/releases/{version}/health",
3841
+ scope: "releases:read",
3842
+ input: N.releaseHealth,
3843
+ node: { path: "q/releases/health" },
3844
+ summary: "One release in one environment against the previous one (or `compare`): new, regressed and increased issues in its first 24 hours (≤ 50 each, with hourly sparklines) and its deploy markers."
3845
+ }),
3846
+ op({
3847
+ ...read,
3848
+ id: "issues.fix_status",
3849
+ path: "/v1/issues/{issue_id}/fix-status",
3850
+ scope: "releases:read",
3851
+ input: N.issue,
3852
+ node: { path: "q/issues/{issue_id}/fix-status" },
3853
+ summary: "Whether a resolved issue is fixed in each environment it occurred in: fixed (a deploy of the target release and 24 h of its signals without the error), unverified, not fixed (with the event that broke it) or unknown; null while unresolved."
3854
+ }),
3855
+ op({
3856
+ ...read,
3857
+ id: "deployments.create",
3858
+ method: "POST",
3859
+ path: "/v1/projects/{project}/deployments",
3860
+ scope: "releases:write",
3861
+ input: N.deploymentCreate,
3862
+ node: { path: "w/releases/deployments", body: "*" },
3863
+ mcp: "configure",
3864
+ summary: "Record that a release was deployed to an environment (a deploy marker for CI without sentry-cli). Answers the marker and `created`; the same `deploy_id` again changes nothing (`created: false`)."
3428
3865
  }),
3429
3866
  op({
3430
3867
  ...read,
@@ -3526,10 +3963,10 @@ var NODE_OPERATIONS = [
3526
3963
  ];
3527
3964
 
3528
3965
  // ../src/shared/contracts/api-ops/privacy.ts
3529
- import { z as z22 } from "zod";
3966
+ import { z as z25 } from "zod";
3530
3967
 
3531
3968
  // ../src/shared/contracts/privacy.ts
3532
- import { z as z21 } from "zod";
3969
+ import { z as z24 } from "zod";
3533
3970
 
3534
3971
  // ../src/shared/privacy/rules.ts
3535
3972
  var PRIVACY_SCHEMA = 1;
@@ -3559,44 +3996,47 @@ var IPV6_RE = new RegExp(`(^|[^0-9A-Fa-f:])((?:${H}:){7}${H}|(?:${H}:){1,6}:(?:$
3559
3996
  var REMOVE = Symbol("remove");
3560
3997
 
3561
3998
  // ../src/shared/contracts/privacy.ts
3562
- var ruleId = z21.string().regex(/^[A-Za-z0-9_-]{1,64}$/);
3563
- var privacyRuleInputSchema = z21.object({
3999
+ var PRIVACY_KEY_MAX_VERSION = 1e6;
4000
+ var ruleId = z24.string().regex(/^[A-Za-z0-9_-]{1,64}$/);
4001
+ var privacyRuleInputSchema = z24.object({
3564
4002
  id: ruleId,
3565
- selector: z21.string().min(1).max(PRIVACY_LIMITS.selector),
3566
- type: z21.enum(PRIVACY_RULE_TYPES),
3567
- method: z21.enum(PRIVACY_METHODS),
3568
- pattern: z21.string().min(1).max(PRIVACY_LIMITS.pattern).optional(),
3569
- ignoreCase: z21.boolean().optional(),
3570
- replaceWith: z21.string().max(PRIVACY_LIMITS.replaceWith).optional(),
3571
- enabled: z21.boolean().optional()
4003
+ selector: z24.string().min(1).max(PRIVACY_LIMITS.selector),
4004
+ type: z24.enum(PRIVACY_RULE_TYPES),
4005
+ method: z24.enum(PRIVACY_METHODS),
4006
+ pattern: z24.string().min(1).max(PRIVACY_LIMITS.pattern).optional(),
4007
+ ignoreCase: z24.boolean().optional(),
4008
+ replaceWith: z24.string().max(PRIVACY_LIMITS.replaceWith).optional(),
4009
+ enabled: z24.boolean().optional()
3572
4010
  });
3573
- var privacyPolicyInputSchema = z21.object({
3574
- mode: z21.enum(PRIVACY_MODES),
3575
- rules: z21.array(privacyRuleInputSchema).max(PRIVACY_LIMITS.rules),
3576
- allowlist: z21.array(z21.string().min(1).max(PRIVACY_LIMITS.selector)).max(PRIVACY_LIMITS.allowlist)
4011
+ var privacyPolicyInputSchema = z24.object({
4012
+ mode: z24.enum(PRIVACY_MODES),
4013
+ rules: z24.array(privacyRuleInputSchema).max(PRIVACY_LIMITS.rules),
4014
+ allowlist: z24.array(z24.string().min(1).max(PRIVACY_LIMITS.selector)).max(PRIVACY_LIMITS.allowlist)
3577
4015
  });
3578
- var storedPolicySchema = z21.object({
3579
- schema: z21.literal(PRIVACY_SCHEMA),
3580
- version: z21.number().int().min(0),
3581
- mode: z21.enum(PRIVACY_MODES),
3582
- rules: z21.array(z21.record(z21.string(), z21.unknown())).max(PRIVACY_LIMITS.rules),
3583
- allowlist: z21.array(z21.string()).max(PRIVACY_LIMITS.allowlist)
4016
+ var storedPolicySchema = z24.object({
4017
+ schema: z24.literal(PRIVACY_SCHEMA),
4018
+ version: z24.number().int().min(0),
4019
+ mode: z24.enum(PRIVACY_MODES),
4020
+ rules: z24.array(z24.record(z24.string(), z24.unknown())).max(PRIVACY_LIMITS.rules),
4021
+ allowlist: z24.array(z24.string()).max(PRIVACY_LIMITS.allowlist)
3584
4022
  });
3585
- var nodePrivacyBlockSchema = z21.array(z21.object({ project_id: z21.number().int().positive(), policy: z21.unknown() })).max(1000);
3586
- var privacyRollupSchema = z21.object({
3587
- applied_version: z21.number().int().min(0).nullable(),
3588
- policy_missing_24h: z21.number().int().nonnegative(),
3589
- budget_exceeded_24h: z21.number().int().nonnegative(),
3590
- sdk_versions: z21.array(z21.object({ version: z21.number().int().min(0), last_seen_at: z21.string().datetime() })).max(5)
4023
+ var nodePrivacyBlockSchema = z24.array(z24.object({ project_id: z24.number().int().positive(), policy: z24.unknown() })).max(1000);
4024
+ var privacyRollupSchema = z24.object({
4025
+ applied_version: z24.number().int().min(0).nullable(),
4026
+ policy_missing_24h: z24.number().int().nonnegative(),
4027
+ budget_exceeded_24h: z24.number().int().nonnegative(),
4028
+ sdk_versions: z24.array(z24.object({ version: z24.number().int().min(0), last_seen_at: z24.string().datetime() })).max(5),
4029
+ key_version: z24.number().int().min(1).max(PRIVACY_KEY_MAX_VERSION).optional(),
4030
+ key_created_at: z24.string().datetime().nullable().optional()
3591
4031
  });
3592
4032
 
3593
4033
  // ../src/shared/contracts/api-ops/privacy.ts
3594
4034
  var PRIVACY_INPUTS = {
3595
- get: z22.object({ workspaceId: uuid, projectId }),
3596
- set: z22.object({
4035
+ get: z25.object({ workspaceId: uuid, projectId }),
4036
+ set: z25.object({
3597
4037
  workspaceId: uuid,
3598
4038
  projectId,
3599
- expectedVersion: z22.number().int().min(0),
4039
+ expectedVersion: z25.number().int().min(0),
3600
4040
  policy: privacyPolicyInputSchema
3601
4041
  })
3602
4042
  };
@@ -3614,7 +4054,7 @@ var PRIVACY_OPERATIONS = [
3614
4054
  workspace: true,
3615
4055
  idempotency: "none",
3616
4056
  mcp: "configure",
3617
- summary: "A project's privacy policy (mode, rules, strict allowlist, version), the built-in detectors that are off, whether user ids are pseudonymised, the last 20 versions and what the node applies and counted in the last 24 h.",
4057
+ summary: "A project's privacy policy (mode, rules, strict allowlist, version), the built-in detectors that are off, whether user ids are pseudonymised, the pseudonymisation key version (never the key), the last 20 versions and what the node applies, hashes with and counted in the last 24 h.",
3618
4058
  ui: []
3619
4059
  }),
3620
4060
  op({
@@ -3636,10 +4076,10 @@ var PRIVACY_OPERATIONS = [
3636
4076
  ];
3637
4077
 
3638
4078
  // ../src/shared/contracts/api-ops/projects.ts
3639
- import { z as z26 } from "zod";
4079
+ import { z as z29 } from "zod";
3640
4080
 
3641
4081
  // ../src/shared/contracts/ingest-keys.ts
3642
- import { z as z23 } from "zod";
4082
+ import { z as z26 } from "zod";
3643
4083
  var INGEST_KEY_SCOPES = ["traces", "logs", "metrics", "errors", "monitors"];
3644
4084
  var INGEST_KEY_STATES = ["active", "revoked"];
3645
4085
  var INGEST_KEY_LIMITS = {
@@ -3649,92 +4089,92 @@ var INGEST_KEY_LIMITS = {
3649
4089
  edgeCacheSeconds: 60
3650
4090
  };
3651
4091
  var CHECKIN_AUTH_MODES = ["public_or_key", "key_only"];
3652
- var ingestKeyConfigSchema = z23.object({
3653
- v: z23.literal(1),
3654
- key_id: z23.guid(),
3655
- project_public_id: z23.number().int().positive(),
3656
- project_id: z23.number().int().positive(),
3657
- workspace_id: z23.guid(),
4092
+ var ingestKeyConfigSchema = z26.object({
4093
+ v: z26.literal(1),
4094
+ key_id: z26.guid(),
4095
+ project_public_id: z26.number().int().positive(),
4096
+ project_id: z26.number().int().positive(),
4097
+ workspace_id: z26.guid(),
3658
4098
  node_id: nodeIdSchema,
3659
- scopes: z23.array(z23.enum(INGEST_KEY_SCOPES)).min(1).max(INGEST_KEY_SCOPES.length),
3660
- environments: z23.array(z23.string().max(INGEST_KEY_LIMITS.environmentMaxChars)).max(INGEST_KEY_LIMITS.environmentsMax),
3661
- expires_at: z23.string().datetime({ offset: true }).nullable(),
3662
- state: z23.enum(INGEST_KEY_STATES),
3663
- workspace_status: z23.enum(["active", "suspended", "deleting"]),
3664
- ingest_kill: z23.boolean(),
3665
- telemetry_kill: z23.boolean(),
3666
- telemetry_rate_bytes_per_sec: z23.number().int().positive(),
3667
- telemetry_burst_bytes: z23.number().int().positive(),
3668
- traces_monthly_bytes: z23.number().int().positive(),
3669
- logs_monthly_bytes: z23.number().int().positive(),
3670
- metrics_monthly_bytes: z23.number().int().positive().optional(),
3671
- telemetry_buffer_minutes: z23.number().int().min(1).max(1440),
3672
- revision: z23.number().int().nonnegative()
4099
+ scopes: z26.array(z26.enum(INGEST_KEY_SCOPES)).min(1).max(INGEST_KEY_SCOPES.length),
4100
+ environments: z26.array(z26.string().max(INGEST_KEY_LIMITS.environmentMaxChars)).max(INGEST_KEY_LIMITS.environmentsMax),
4101
+ expires_at: z26.string().datetime({ offset: true }).nullable(),
4102
+ state: z26.enum(INGEST_KEY_STATES),
4103
+ workspace_status: z26.enum(["active", "suspended", "deleting"]),
4104
+ ingest_kill: z26.boolean(),
4105
+ telemetry_kill: z26.boolean(),
4106
+ telemetry_rate_bytes_per_sec: z26.number().int().positive(),
4107
+ telemetry_burst_bytes: z26.number().int().positive(),
4108
+ traces_monthly_bytes: z26.number().int().positive(),
4109
+ logs_monthly_bytes: z26.number().int().positive(),
4110
+ metrics_monthly_bytes: z26.number().int().positive().optional(),
4111
+ telemetry_buffer_minutes: z26.number().int().min(1).max(1440),
4112
+ revision: z26.number().int().nonnegative()
3673
4113
  });
3674
- var createIngestKeyInputSchema = z23.object({
3675
- projectId: z23.number().int().positive(),
3676
- name: z23.string().trim().min(1).max(INGEST_KEY_LIMITS.nameMaxChars).refine((s) => !/[\u0000-\u001f\u007f]/.test(s)),
3677
- scopes: z23.array(z23.enum(INGEST_KEY_SCOPES)).min(1).max(INGEST_KEY_SCOPES.length),
3678
- environments: z23.array(z23.string().trim().min(1).max(INGEST_KEY_LIMITS.environmentMaxChars).regex(/^[^\s/\u0000-\u001f]+$/)).max(INGEST_KEY_LIMITS.environmentsMax),
3679
- expiresAt: z23.string().datetime({ offset: true }).nullable()
4114
+ var createIngestKeyInputSchema = z26.object({
4115
+ projectId: z26.number().int().positive(),
4116
+ name: z26.string().trim().min(1).max(INGEST_KEY_LIMITS.nameMaxChars).refine((s) => !/[\u0000-\u001f\u007f]/.test(s)),
4117
+ scopes: z26.array(z26.enum(INGEST_KEY_SCOPES)).min(1).max(INGEST_KEY_SCOPES.length),
4118
+ environments: z26.array(z26.string().trim().min(1).max(INGEST_KEY_LIMITS.environmentMaxChars).regex(/^[^\s/\u0000-\u001f]+$/)).max(INGEST_KEY_LIMITS.environmentsMax),
4119
+ expiresAt: z26.string().datetime({ offset: true }).nullable()
3680
4120
  });
3681
- var ingestKeyRowSchema = z23.object({
3682
- id: z23.guid(),
3683
- project_id: z23.number().int().positive(),
3684
- name: z23.string(),
3685
- prefix: z23.string(),
3686
- scopes: z23.array(z23.enum(INGEST_KEY_SCOPES)),
3687
- environments: z23.array(z23.string()),
3688
- expires_at: z23.string().nullable(),
3689
- state: z23.enum(INGEST_KEY_STATES),
3690
- created_by: z23.guid().nullable(),
3691
- created_at: z23.string(),
3692
- revoked_at: z23.string().nullable(),
3693
- last_used_at: z23.string().nullable()
4121
+ var ingestKeyRowSchema = z26.object({
4122
+ id: z26.guid(),
4123
+ project_id: z26.number().int().positive(),
4124
+ name: z26.string(),
4125
+ prefix: z26.string(),
4126
+ scopes: z26.array(z26.enum(INGEST_KEY_SCOPES)),
4127
+ environments: z26.array(z26.string()),
4128
+ expires_at: z26.string().nullable(),
4129
+ state: z26.enum(INGEST_KEY_STATES),
4130
+ created_by: z26.guid().nullable(),
4131
+ created_at: z26.string(),
4132
+ revoked_at: z26.string().nullable(),
4133
+ last_used_at: z26.string().nullable()
3694
4134
  });
3695
4135
 
3696
4136
  // ../src/shared/contracts/node-config.ts
3697
- import { z as z25 } from "zod";
4137
+ import { z as z28 } from "zod";
3698
4138
 
3699
4139
  // ../src/shared/contracts/backup.ts
3700
- import { z as z24 } from "zod";
4140
+ import { z as z27 } from "zod";
3701
4141
  var BACKUP_KINDS = ["daily", "weekly", "manual", "pre_upgrade"];
3702
- var ageRecipient = z24.string().regex(/^age1[02-9ac-hj-np-z]{58}$/);
3703
- var backupIdSchema = z24.string().regex(/^[a-z0-9-]{8,64}$/);
3704
- var nodeBackupConfigSchema = z24.object({
3705
- enabled: z24.boolean(),
3706
- hour_utc: z24.number().int().min(0).max(23),
3707
- weekly_day: z24.number().int().min(1).max(7),
4142
+ var ageRecipient = z27.string().regex(/^age1[02-9ac-hj-np-z]{58}$/);
4143
+ var backupIdSchema = z27.string().regex(/^[a-z0-9-]{8,64}$/);
4144
+ var nodeBackupConfigSchema = z27.object({
4145
+ enabled: z27.boolean(),
4146
+ hour_utc: z27.number().int().min(0).max(23),
4147
+ weekly_day: z27.number().int().min(1).max(7),
3708
4148
  workspace_recipient: ageRecipient
3709
4149
  });
3710
- var backupCredentialsRequestSchema = z24.object({
3711
- mode: z24.enum(["upload", "download"]),
4150
+ var backupCredentialsRequestSchema = z27.object({
4151
+ mode: z27.enum(["upload", "download"]),
3712
4152
  backup_id: backupIdSchema,
3713
- source_node_id: z24.guid().optional()
4153
+ source_node_id: z27.guid().optional()
3714
4154
  });
3715
- var backupCredentialsSchema = z24.object({
3716
- endpoint: z24.string().url(),
3717
- bucket: z24.string().regex(/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/),
3718
- prefix: z24.string().regex(/^backups\/[0-9a-f-]{36}\/$/),
3719
- access_key_id: z24.string().min(8).max(200),
3720
- secret_access_key: z24.string().min(8).max(200),
3721
- session_token: z24.string().min(8).max(4000),
3722
- expires_at: z24.string().datetime()
4155
+ var backupCredentialsSchema = z27.object({
4156
+ endpoint: z27.string().url(),
4157
+ bucket: z27.string().regex(/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/),
4158
+ prefix: z27.string().regex(/^backups\/[0-9a-f-]{36}\/$/),
4159
+ access_key_id: z27.string().min(8).max(200),
4160
+ secret_access_key: z27.string().min(8).max(200),
4161
+ session_token: z27.string().min(8).max(4000),
4162
+ expires_at: z27.string().datetime()
3723
4163
  });
3724
- var rowCountsSchema = z24.record(z24.string().regex(/^[a-z_][a-z0-9_]{0,63}$/), z24.number().int().nonnegative());
3725
- var backupManifestSchema = z24.object({
3726
- v: z24.literal(1),
4164
+ var rowCountsSchema = z27.record(z27.string().regex(/^[a-z_][a-z0-9_]{0,63}$/), z27.number().int().nonnegative());
4165
+ var backupManifestSchema = z27.object({
4166
+ v: z27.literal(1),
3727
4167
  backup_id: backupIdSchema,
3728
- node_id: z24.guid(),
3729
- kind: z24.enum(BACKUP_KINDS),
3730
- created_at: z24.string().datetime(),
3731
- object_key: z24.string(),
3732
- size_bytes: z24.number().int().nonnegative(),
3733
- sha256: z24.string().regex(/^[0-9a-f]{64}$/),
3734
- clickhouse_version: z24.string().max(40),
3735
- schema_version: z24.number().int().nonnegative(),
4168
+ node_id: z27.guid(),
4169
+ kind: z27.enum(BACKUP_KINDS),
4170
+ created_at: z27.string().datetime(),
4171
+ object_key: z27.string(),
4172
+ size_bytes: z27.number().int().nonnegative(),
4173
+ sha256: z27.string().regex(/^[0-9a-f]{64}$/),
4174
+ clickhouse_version: z27.string().max(40),
4175
+ schema_version: z27.number().int().nonnegative(),
3736
4176
  row_counts: rowCountsSchema,
3737
- recipients: z24.array(z24.string().regex(/^[0-9a-f]{8}$/)).min(1).max(4)
4177
+ recipients: z27.array(z27.string().regex(/^[0-9a-f]{8}$/)).min(1).max(4)
3738
4178
  });
3739
4179
  var BACKUP_ERROR_CODES = [
3740
4180
  "CLICKHOUSE_BACKUP_FAILED",
@@ -3748,48 +4188,48 @@ var BACKUP_ERROR_CODES = [
3748
4188
  "RESTORE_FAILED",
3749
4189
  "ROW_COUNT_MISMATCH"
3750
4190
  ];
3751
- var backupReportSchema = z24.object({
4191
+ var backupReportSchema = z27.object({
3752
4192
  backup_id: backupIdSchema,
3753
- kind: z24.enum(BACKUP_KINDS),
3754
- status: z24.enum(["succeeded", "failed"]),
3755
- started_at: z24.string().datetime(),
3756
- finished_at: z24.string().datetime(),
4193
+ kind: z27.enum(BACKUP_KINDS),
4194
+ status: z27.enum(["succeeded", "failed"]),
4195
+ started_at: z27.string().datetime(),
4196
+ finished_at: z27.string().datetime(),
3757
4197
  manifest: backupManifestSchema.nullable(),
3758
- error_code: z24.enum(BACKUP_ERROR_CODES).nullable()
4198
+ error_code: z27.enum(BACKUP_ERROR_CODES).nullable()
3759
4199
  });
3760
- var drillReportSchema = z24.object({
4200
+ var drillReportSchema = z27.object({
3761
4201
  backup_id: backupIdSchema,
3762
- kind: z24.enum(["weekly_local", "monthly_new_machine"]),
3763
- status: z24.enum(["passed", "failed"]),
3764
- finished_at: z24.string().datetime(),
3765
- detail: z24.string().max(300),
3766
- error_code: z24.enum(BACKUP_ERROR_CODES).nullable()
4202
+ kind: z27.enum(["weekly_local", "monthly_new_machine"]),
4203
+ status: z27.enum(["passed", "failed"]),
4204
+ finished_at: z27.string().datetime(),
4205
+ detail: z27.string().max(300),
4206
+ error_code: z27.enum(BACKUP_ERROR_CODES).nullable()
3767
4207
  });
3768
- var nodeIdentityEscrowSchema = z24.object({
3769
- v: z24.literal(1),
3770
- node_id: z24.guid(),
3771
- seal: z24.object({
3772
- publicKey: z24.string().regex(/^[A-Za-z0-9_-]{43}$/),
3773
- privateKey: z24.string().regex(/^[A-Za-z0-9_-]{43}$/)
3774
- }),
3775
- created_at: z24.string().datetime()
4208
+ var nodeIdentityEscrowSchema = z27.object({
4209
+ v: z27.literal(1),
4210
+ node_id: z27.guid(),
4211
+ seal: z27.object({
4212
+ publicKey: z27.string().regex(/^[A-Za-z0-9_-]{43}$/),
4213
+ privateKey: z27.string().regex(/^[A-Za-z0-9_-]{43}$/)
4214
+ }),
4215
+ created_at: z27.string().datetime()
3776
4216
  });
3777
- var restoreArgsSchema = z24.object({
3778
- job_id: z24.guid(),
3779
- workspace_id: z24.guid(),
3780
- source_node_id: z24.guid(),
4217
+ var restoreArgsSchema = z27.object({
4218
+ job_id: z27.guid(),
4219
+ workspace_id: z27.guid(),
4220
+ source_node_id: z27.guid(),
3781
4221
  manifest: backupManifestSchema,
3782
- sealed_identity: z24.string().regex(/^[A-Za-z0-9_-]{40,2000}$/),
3783
- mode: z24.enum(["rebuild", "drill"])
4222
+ sealed_identity: z27.string().regex(/^[A-Za-z0-9_-]{40,2000}$/),
4223
+ mode: z27.enum(["rebuild", "drill"])
3784
4224
  });
3785
- var restoreReportSchema = z24.object({
3786
- job_id: z24.guid(),
4225
+ var restoreReportSchema = z27.object({
4226
+ job_id: z27.guid(),
3787
4227
  backup_id: backupIdSchema,
3788
- mode: z24.enum(["rebuild", "drill"]),
3789
- status: z24.enum(["succeeded", "failed"]),
3790
- finished_at: z24.string().datetime(),
3791
- detail: z24.string().max(300),
3792
- error_code: z24.enum(BACKUP_ERROR_CODES).nullable()
4228
+ mode: z27.enum(["rebuild", "drill"]),
4229
+ status: z27.enum(["succeeded", "failed"]),
4230
+ finished_at: z27.string().datetime(),
4231
+ detail: z27.string().max(300),
4232
+ error_code: z27.enum(BACKUP_ERROR_CODES).nullable()
3793
4233
  });
3794
4234
 
3795
4235
  // ../src/shared/contracts/node-config.ts
@@ -3803,83 +4243,85 @@ var SCRUB_GROUPS = [
3803
4243
  "headers"
3804
4244
  ];
3805
4245
  var MAX_NODE_MONITORS = 5000;
3806
- var kid = z25.string().regex(/^[A-Za-z0-9_-]{1,40}$/);
3807
- var publicKey = z25.string().regex(/^[A-Za-z0-9_-]{43}$/);
3808
- var nodeConfigSchema = z25.object({
3809
- v: z25.literal(1),
3810
- config_version: z25.number().int().positive(),
3811
- node_id: z25.guid(),
3812
- workspace_id: z25.guid(),
3813
- workspace_status: z25.enum(["active", "suspended"]),
3814
- issued_at: z25.string().datetime(),
3815
- retention_days: z25.number().int().min(1).max(3650),
3816
- channel: z25.enum(["stable", "canary"]).optional(),
3817
- projects: z25.array(z25.object({
3818
- project_id: z25.number().int().positive(),
3819
- slug: z25.string().max(64),
3820
- short_prefix: z25.string().regex(/^[A-Z0-9]{1,12}$/),
3821
- user_id_salt: z25.string().regex(/^[A-Za-z0-9_-]{22,64}$/),
3822
- scrub_disabled: z25.array(z25.enum(SCRUB_GROUPS)).max(SCRUB_GROUPS.length),
3823
- upload_tokens: z25.array(z25.object({
3824
- hash: z25.string().regex(/^[a-f0-9]{64}$/),
3825
- expires_at: z25.string().datetime()
4246
+ var kid = z28.string().regex(/^[A-Za-z0-9_-]{1,40}$/);
4247
+ var publicKey = z28.string().regex(/^[A-Za-z0-9_-]{43}$/);
4248
+ var nodeConfigSchema = z28.object({
4249
+ v: z28.literal(1),
4250
+ config_version: z28.number().int().positive(),
4251
+ node_id: z28.guid(),
4252
+ workspace_id: z28.guid(),
4253
+ workspace_status: z28.enum(["active", "suspended"]),
4254
+ issued_at: z28.string().datetime(),
4255
+ retention_days: z28.number().int().min(1).max(3650),
4256
+ channel: z28.enum(["stable", "canary"]).optional(),
4257
+ projects: z28.array(z28.object({
4258
+ project_id: z28.number().int().positive(),
4259
+ slug: z28.string().max(64),
4260
+ short_prefix: z28.string().regex(/^[A-Z0-9]{1,12}$/),
4261
+ user_id_salt: z28.string().regex(/^[A-Za-z0-9_-]{22,64}$/),
4262
+ privacy_key_version: z28.number().int().min(1).max(PRIVACY_KEY_MAX_VERSION).optional(),
4263
+ scrub_disabled: z28.array(z28.enum(SCRUB_GROUPS)).max(SCRUB_GROUPS.length),
4264
+ upload_tokens: z28.array(z28.object({
4265
+ hash: z28.string().regex(/^[a-f0-9]{64}$/),
4266
+ expires_at: z28.string().datetime(),
4267
+ scopes: z28.array(z28.enum(UPLOAD_SCOPES)).min(1).max(UPLOAD_SCOPES.length).optional()
3826
4268
  })).max(10).optional()
3827
4269
  })).max(1000),
3828
- ticket_keys: z25.array(z25.object({ kid, public_key: publicKey, not_after: z25.string().datetime() })).min(1).max(5),
3829
- control_ops_keys: z25.array(z25.object({ kid, public_key: publicKey })).min(1).max(5),
3830
- kill_switches: z25.object({ ingest: z25.boolean(), alerts: z25.boolean() }),
4270
+ ticket_keys: z28.array(z28.object({ kid, public_key: publicKey, not_after: z28.string().datetime() })).min(1).max(5),
4271
+ control_ops_keys: z28.array(z28.object({ kid, public_key: publicKey })).min(1).max(5),
4272
+ kill_switches: z28.object({ ingest: z28.boolean(), alerts: z28.boolean() }),
3831
4273
  backup: nodeBackupConfigSchema.optional(),
3832
- purged_projects: z25.array(z25.number().int().positive()).max(1000).optional(),
3833
- monitors: z25.array(monitorDefinitionSchema).max(MAX_NODE_MONITORS).optional(),
3834
- purged_monitors: z25.array(z25.guid()).max(5000).optional(),
3835
- telemetry: z25.object({
3836
- traces_retention_days: z25.number().int().min(1).max(90),
3837
- logs_retention_days: z25.number().int().min(1).max(90),
3838
- traces_disk_share: z25.number().min(0.2).max(0.8)
4274
+ purged_projects: z28.array(z28.number().int().positive()).max(1000).optional(),
4275
+ monitors: z28.array(monitorDefinitionSchema).max(MAX_NODE_MONITORS).optional(),
4276
+ purged_monitors: z28.array(z28.guid()).max(5000).optional(),
4277
+ telemetry: z28.object({
4278
+ traces_retention_days: z28.number().int().min(1).max(90),
4279
+ logs_retention_days: z28.number().int().min(1).max(90),
4280
+ traces_disk_share: z28.number().min(0.2).max(0.8)
3839
4281
  }).optional(),
3840
4282
  metrics: metricsConfigSchema.optional(),
3841
- slos: z25.array(nodeSloSchema).max(SLO_LIMITS.maxNodeSlos).optional(),
3842
- signal_monitors: z25.array(signalMonitorDefinitionSchema).max(MAX_NODE_MONITORS).optional(),
4283
+ slos: z28.array(nodeSloSchema).max(SLO_LIMITS.maxNodeSlos).optional(),
4284
+ signal_monitors: z28.array(signalMonitorDefinitionSchema).max(MAX_NODE_MONITORS).optional(),
3843
4285
  signal_limits: signalLimitsConfigSchema.optional(),
3844
4286
  privacy: nodePrivacyBlockSchema.optional()
3845
4287
  });
3846
- var signedNodeConfigSchema = z25.object({ config: nodeConfigSchema, kid, sig: z25.string() });
4288
+ var signedNodeConfigSchema = z28.object({ config: nodeConfigSchema, kid, sig: z28.string() });
3847
4289
 
3848
4290
  // ../src/shared/contracts/api-ops/projects.ts
3849
- var slug = z26.string().regex(/^[a-z0-9][a-z0-9-]{1,38}[a-z0-9]$/);
3850
- var name3 = z26.string().trim().min(1).max(60);
3851
- var label2 = z26.string().trim().min(1).max(40);
3852
- var platform = z26.enum(PLATFORMS);
3853
- var origin = z26.string().trim().toLowerCase().regex(/^https?:\/\/[a-z0-9.-]+(:[0-9]{1,5})?$/).max(200);
3854
- var keyId = z26.number().int().positive();
4291
+ var slug = z29.string().regex(/^[a-z0-9][a-z0-9-]{1,38}[a-z0-9]$/);
4292
+ var name3 = z29.string().trim().min(1).max(60);
4293
+ var label2 = z29.string().trim().min(1).max(40);
4294
+ var platform = z29.enum(PLATFORMS);
4295
+ var origin = z29.string().trim().toLowerCase().regex(/^https?:\/\/[a-z0-9.-]+(:[0-9]{1,5})?$/).max(200);
4296
+ var keyId = z29.number().int().positive();
3855
4297
  var PROJECT_INPUTS = {
3856
- create: z26.object({ workspaceId: uuid, name: name3, slug, platform }),
3857
- update: z26.object({ projectId, name: name3, platform, isPinned: z26.boolean() }),
3858
- updateIntake: z26.object({
4298
+ create: z29.object({ workspaceId: uuid, name: name3, slug, platform }),
4299
+ update: z29.object({ projectId, name: name3, platform, isPinned: z29.boolean() }),
4300
+ updateIntake: z29.object({
3859
4301
  projectId,
3860
- rateLimit: z26.number().int().positive().nullable(),
3861
- burst: z26.number().int().positive().nullable(),
3862
- allowedOrigins: z26.array(origin).max(50)
4302
+ rateLimit: z29.number().int().positive().nullable(),
4303
+ burst: z29.number().int().positive().nullable(),
4304
+ allowedOrigins: z29.array(origin).max(50)
3863
4305
  }),
3864
- updateObservability: z26.object({
4306
+ updateObservability: z29.object({
3865
4307
  projectId,
3866
- primaryEnvironment: z26.string().trim().min(1).max(64).refine((v) => v !== "*" && ENVIRONMENT_RE.test(v)),
3867
- allowCodeMonitors: z26.boolean()
4308
+ primaryEnvironment: z29.string().trim().min(1).max(64).refine((v) => v !== "*" && ENVIRONMENT_RE.test(v)),
4309
+ allowCodeMonitors: z29.boolean()
3868
4310
  }),
3869
- setScrub: z26.object({ projectId, group: z26.enum(SCRUB_GROUPS), enabled: z26.boolean() }),
3870
- setCheckinAuth: z26.object({ projectId, mode: z26.enum(CHECKIN_AUTH_MODES) }),
3871
- setEnvironmentHidden: z26.object({
4311
+ setScrub: z29.object({ projectId, group: z29.enum(SCRUB_GROUPS), enabled: z29.boolean() }),
4312
+ setCheckinAuth: z29.object({ projectId, mode: z29.enum(CHECKIN_AUTH_MODES) }),
4313
+ setEnvironmentHidden: z29.object({
3872
4314
  projectId,
3873
- name: z26.string().min(1).max(64),
3874
- hidden: z26.boolean()
3875
- }),
3876
- scheduleDeletion: z26.object({ projectId, confirmSlug: slug }),
3877
- projectOnly: z26.object({ projectId }),
3878
- labelled: z26.object({ projectId, label: label2 }),
3879
- keyOnly: z26.object({ keyId }),
3880
- tokenOnly: z26.object({ tokenId: keyId }),
4315
+ name: z29.string().min(1).max(64),
4316
+ hidden: z29.boolean()
4317
+ }),
4318
+ scheduleDeletion: z29.object({ projectId, confirmSlug: slug }),
4319
+ projectOnly: z29.object({ projectId }),
4320
+ labelled: z29.object({ projectId, label: label2 }),
4321
+ keyOnly: z29.object({ keyId }),
4322
+ tokenOnly: z29.object({ tokenId: keyId }),
3881
4323
  createIngestKey: createIngestKeyInputSchema,
3882
- ingestKeyOnly: z26.object({ keyId: uuid })
4324
+ ingestKeyOnly: z29.object({ keyId: uuid })
3883
4325
  };
3884
4326
  var P2 = PROJECT_INPUTS;
3885
4327
  var PROJECT_OPERATIONS = [
@@ -4134,24 +4576,24 @@ var PROJECT_OPERATIONS = [
4134
4576
  ];
4135
4577
 
4136
4578
  // ../src/shared/contracts/api-ops/reads.ts
4137
- import { z as z27 } from "zod";
4138
- var list = z27.object({ workspaceId: uuid, limit: pageLimit, cursor });
4579
+ import { z as z30 } from "zod";
4580
+ var list = z30.object({ workspaceId: uuid, limit: pageLimit, cursor });
4139
4581
  var READ_INPUTS = {
4140
- workspace: z27.object({ workspaceId: uuid }),
4582
+ workspace: z30.object({ workspaceId: uuid }),
4141
4583
  list,
4142
- projectsGet: z27.object({ workspaceId: uuid, projectId }),
4584
+ projectsGet: z30.object({ workspaceId: uuid, projectId }),
4143
4585
  monitorsList: list.extend({ projectId: projectId.optional() }),
4144
- monitorsGet: z27.object({ workspaceId: uuid, monitorId: uuid }),
4145
- uptimeGet: z27.object({ workspaceId: uuid, checkId: uuid }),
4146
- slosGet: z27.object({ workspaceId: uuid, sloId: uuid }),
4586
+ monitorsGet: z30.object({ workspaceId: uuid, monitorId: uuid }),
4587
+ uptimeGet: z30.object({ workspaceId: uuid, checkId: uuid }),
4588
+ slosGet: z30.object({ workspaceId: uuid, sloId: uuid }),
4147
4589
  alertsList: list.extend({
4148
- state: z27.enum(["open", "resolved", "all"]).default("all"),
4590
+ state: z30.enum(["open", "resolved", "all"]).default("all"),
4149
4591
  monitorId: uuid.optional()
4150
4592
  }),
4151
- approvalsGet: z27.object({ workspaceId: uuid, approvalId: uuid }),
4593
+ approvalsGet: z30.object({ workspaceId: uuid, approvalId: uuid }),
4152
4594
  monitorsListTyped: list.extend({
4153
4595
  projectId: projectId.optional(),
4154
- type: z27.enum(MONITOR_TYPES).optional()
4596
+ type: z30.enum(MONITOR_TYPES).optional()
4155
4597
  })
4156
4598
  };
4157
4599
  var R = READ_INPUTS;
@@ -4435,14 +4877,14 @@ function approvalRequestSchema(operationId, input) {
4435
4877
  }
4436
4878
 
4437
4879
  // ../src/shared/contracts/api-ops/wire.ts
4438
- import { z as z28 } from "zod";
4880
+ import { z as z31 } from "zod";
4439
4881
  var toSnake = (s) => s.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
4440
4882
  var toCamel = (s) => s.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase());
4441
4883
  var schemaCache = new WeakMap;
4442
4884
  function inputJsonSchema(op) {
4443
4885
  let js = schemaCache.get(op.input);
4444
4886
  if (!js) {
4445
- js = z28.toJSONSchema(op.input, { io: "input", unrepresentable: "any" });
4887
+ js = z31.toJSONSchema(op.input, { io: "input", unrepresentable: "any" });
4446
4888
  schemaCache.set(op.input, js);
4447
4889
  }
4448
4890
  return js;
@@ -4656,7 +5098,7 @@ function wireInput(operationId, opts = {}) {
4656
5098
  for (const [k, v] of Object.entries(op.input.shape))
4657
5099
  if (!omit.has(k))
4658
5100
  shape[toSnake(k)] = v;
4659
- return z29.object(shape);
5101
+ return z32.object(shape);
4660
5102
  }
4661
5103
  var BUDGETS = [
4662
5104
  { stringBytes: MCP_LIMITS.untrustedStringMaxBytes, listMax: MCP_LIMITS.listMax },
@@ -4716,7 +5158,10 @@ function untrustedTree(value, reserveBytes = 2048) {
4716
5158
  function wrapResult(parts, extra = {}) {
4717
5159
  const t = untrustedTree(parts.data);
4718
5160
  const structuredContent = {
4719
- untrusted: { data: t.data, provenance: { source: parts.source, operations: [...parts.operations] } }
5161
+ untrusted: {
5162
+ data: t.data,
5163
+ provenance: { source: parts.source, operations: [...parts.operations] }
5164
+ }
4720
5165
  };
4721
5166
  if (extra.next_cursor !== undefined) {
4722
5167
  const c = extra.next_cursor === null ? null : cleanUntrustedText(extra.next_cursor, 600).text;
@@ -4746,40 +5191,52 @@ function errorResult(o) {
4746
5191
  }
4747
5192
  };
4748
5193
  }
4749
- var TOOL_OUTPUT_SCHEMA = z29.object({
4750
- untrusted: z29.object({
4751
- data: z29.unknown(),
4752
- provenance: z29.object({
4753
- source: z29.enum(["node", "control_plane", "docs"]),
4754
- operations: z29.array(z29.string())
5194
+ var TOOL_OUTPUT_SCHEMA = z32.object({
5195
+ untrusted: z32.object({
5196
+ data: z32.unknown(),
5197
+ provenance: z32.object({
5198
+ source: z32.enum(["node", "control_plane", "docs"]),
5199
+ operations: z32.array(z32.string())
4755
5200
  })
4756
5201
  }).optional(),
4757
- doc: z29.object({ slug: z29.string(), locale: z29.enum(["en", "vi"]), url: z29.string(), markdown: z29.string(), truncated: z29.boolean() }).optional(),
4758
- results: z29.array(z29.object({ slug: z29.string(), title: z29.string(), description: z29.string(), section: z29.string(), url: z29.string() })).optional(),
4759
- next_cursor: z29.string().nullable().optional(),
4760
- complete: z29.boolean().optional(),
4761
- omitted: z29.array(z29.object({ part: z29.string(), reason: z29.string(), scope: z29.string().optional() })).optional(),
4762
- truncated: z29.literal(true).optional(),
4763
- suspicious_unicode: z29.literal(true).optional(),
4764
- error: z29.object({
4765
- code: z29.string(),
4766
- status: z29.number(),
4767
- detail: z29.string().optional(),
4768
- scope: z29.string().optional(),
4769
- retry_after: z29.number().optional()
5202
+ doc: z32.object({
5203
+ slug: z32.string(),
5204
+ locale: z32.enum(["en", "vi"]),
5205
+ url: z32.string(),
5206
+ markdown: z32.string(),
5207
+ truncated: z32.boolean()
5208
+ }).optional(),
5209
+ results: z32.array(z32.object({
5210
+ slug: z32.string(),
5211
+ title: z32.string(),
5212
+ description: z32.string(),
5213
+ section: z32.string(),
5214
+ url: z32.string()
5215
+ })).optional(),
5216
+ next_cursor: z32.string().nullable().optional(),
5217
+ complete: z32.boolean().optional(),
5218
+ omitted: z32.array(z32.object({ part: z32.string(), reason: z32.string(), scope: z32.string().optional() })).optional(),
5219
+ truncated: z32.literal(true).optional(),
5220
+ suspicious_unicode: z32.literal(true).optional(),
5221
+ error: z32.object({
5222
+ code: z32.string(),
5223
+ status: z32.number(),
5224
+ detail: z32.string().optional(),
5225
+ scope: z32.string().optional(),
5226
+ retry_after: z32.number().optional()
4770
5227
  }).optional(),
4771
- operations: z29.array(z29.record(z29.string(), z29.unknown())).optional(),
4772
- operation: z29.record(z29.string(), z29.unknown()).optional(),
4773
- plan: z29.record(z29.string(), z29.unknown()).optional(),
4774
- status: z29.enum(["done", "approval_required", "approval_pending", ...APPROVAL_STATES]).optional(),
4775
- approval: z29.object({
4776
- approval_id: z29.string(),
4777
- approval_url: z29.string(),
4778
- expires_at: z29.string(),
4779
- state: z29.enum(APPROVAL_STATES),
4780
- result_code: z29.string().nullable().optional(),
4781
- result: z29.record(z29.string(), z29.unknown()).optional(),
4782
- next: z29.string().optional()
5228
+ operations: z32.array(z32.record(z32.string(), z32.unknown())).optional(),
5229
+ operation: z32.record(z32.string(), z32.unknown()).optional(),
5230
+ plan: z32.record(z32.string(), z32.unknown()).optional(),
5231
+ status: z32.enum(["done", "approval_required", "approval_pending", ...APPROVAL_STATES]).optional(),
5232
+ approval: z32.object({
5233
+ approval_id: z32.string(),
5234
+ approval_url: z32.string(),
5235
+ expires_at: z32.string(),
5236
+ state: z32.enum(APPROVAL_STATES),
5237
+ result_code: z32.string().nullable().optional(),
5238
+ result: z32.record(z32.string(), z32.unknown()).optional(),
5239
+ next: z32.string().optional()
4783
5240
  }).optional()
4784
5241
  });
4785
5242
  var spec = (name) => {
@@ -4825,10 +5282,10 @@ var has = (rt, operationId) => {
4825
5282
  return !!op && rt.scopes.includes(op.scope);
4826
5283
  };
4827
5284
  var isoWindow = {
4828
- start: z29.string().max(40).describe("RFC 3339 start of the window, e.g. 2026-10-26T00:00:00Z. Required with end."),
4829
- end: z29.string().max(40).describe("RFC 3339 end of the window. The plan limits its length.")
5285
+ start: z32.string().max(40).describe("RFC 3339 start of the window, e.g. 2026-10-26T00:00:00Z. Required with end."),
5286
+ end: z32.string().max(40).describe("RFC 3339 end of the window. The plan limits its length.")
4830
5287
  };
4831
- var traceIdSchema = z29.string().regex(/^[0-9a-fA-F]{32}$/);
5288
+ var traceIdSchema = z32.string().regex(/^[0-9a-fA-F]{32}$/);
4832
5289
  var MONITOR_KINDS2 = {
4833
5290
  cron: { list: "monitors.list", get: "monitors.get", idField: "monitor_id" },
4834
5291
  uptime: { list: "uptime.list", get: "uptime.get", idField: "check_id" },
@@ -4892,8 +5349,8 @@ function describe(op, scopes) {
4892
5349
  destructive: isDestructiveOperation(op)
4893
5350
  };
4894
5351
  }
4895
- var params = z29.record(z29.string(), z29.unknown()).default({}).describe("Operation fields in wire names (snake_case), as describe_operation's args_schema shows.");
4896
- var operationIdArg = z29.string().min(3).max(80).describe("An operation id from search_operations, e.g. `monitors.update`.");
5352
+ var params = z32.record(z32.string(), z32.unknown()).default({}).describe("Operation fields in wire names (snake_case), as describe_operation's args_schema shows.");
5353
+ var operationIdArg = z32.string().min(3).max(80).describe("An operation id from search_operations, e.g. `monitors.update`.");
4897
5354
  function approvalBlock(t, next) {
4898
5355
  return {
4899
5356
  approval_id: t.approval_id,
@@ -4913,7 +5370,7 @@ var MCP_TOOL_DEFS = [
4913
5370
  title: "Workspace and node",
4914
5371
  description: "The workspace this token belongs to (name, plan, limits) and the state of its node, the server that stores errors, traces and logs. Start here to learn what the token can reach.",
4915
5372
  operations: ["workspace.get", "node.get"],
4916
- input: z29.object({}),
5373
+ input: z32.object({}),
4917
5374
  async run(_args, rt) {
4918
5375
  const [ws, node] = await Promise.all([rt.call("workspace.get", {}), rt.call("node.get", {})]);
4919
5376
  if (!ws.ok)
@@ -4921,7 +5378,11 @@ var MCP_TOOL_DEFS = [
4921
5378
  const omitted = [];
4922
5379
  if (!node.ok)
4923
5380
  omitted.push({ part: "node", reason: node.code });
4924
- return wrapResult({ data: { workspace: ws.body, node: node.ok ? node.body : null }, operations: ["workspace.get", "node.get"], source: "control_plane" }, { omitted });
5381
+ return wrapResult({
5382
+ data: { workspace: ws.body, node: node.ok ? node.body : null },
5383
+ operations: ["workspace.get", "node.get"],
5384
+ source: "control_plane"
5385
+ }, { omitted });
4925
5386
  }
4926
5387
  },
4927
5388
  single("list_projects", "projects.list", "List projects", "Projects this token can read, with their numeric ids (use them as `project` in other tools), platforms and environments."),
@@ -4929,11 +5390,11 @@ var MCP_TOOL_DEFS = [
4929
5390
  {
4930
5391
  ...spec("get_issue"),
4931
5392
  title: "Get an issue",
4932
- description: "One issue with its 24 h and 30 d counts and, when the token can read events, its latest event (stack trace, request, breadcrumbs — scrubbed on the node).",
4933
- operations: ["issues.get", "events.get"],
4934
- input: z29.object({
4935
- issue_id: z29.number().int().positive().describe("Issue id from search_issues."),
4936
- include_latest_event: z29.boolean().default(true)
5393
+ description: "One issue with its 24 h and 30 d counts and, when the token can read events, its latest event (stack trace, request, breadcrumbs — scrubbed on the node). A resolved issue also carries `fix_status` when the token can read releases: fixed, unverified, not_fixed (with the event that broke it) or unknown, per environment.",
5394
+ operations: ["issues.get", "events.get", "issues.fix_status"],
5395
+ input: z32.object({
5396
+ issue_id: z32.number().int().positive().describe("Issue id from search_issues."),
5397
+ include_latest_event: z32.boolean().default(true)
4937
5398
  }),
4938
5399
  async run(args, rt) {
4939
5400
  const omitted = [];
@@ -4951,7 +5412,20 @@ var MCP_TOOL_DEFS = [
4951
5412
  latest = ev.body;
4952
5413
  else if (ev)
4953
5414
  omitted.push({ part: "latest_event", reason: ev.code });
4954
- return wrapResult({ data: { issue: issue.body, latest_event: latest }, operations: ["issues.get", "events.get"], source: "node" }, { omitted });
5415
+ const ops = ["issues.get", "events.get"];
5416
+ const data = { issue: issue.body, latest_event: latest };
5417
+ const resolved = issue.body?.issue?.status === "resolved";
5418
+ if (resolved && !has(rt, "issues.fix_status"))
5419
+ omitted.push({ part: "fix_status", reason: "scope", scope: "releases:read" });
5420
+ else if (resolved) {
5421
+ const fx = await rt.call("issues.fix_status", { issue_id: args["issue_id"] });
5422
+ ops.push("issues.fix_status");
5423
+ if (fx.ok)
5424
+ data["fix_status"] = fx.body;
5425
+ else
5426
+ omitted.push({ part: "fix_status", reason: fx.code });
5427
+ }
5428
+ return wrapResult({ data, operations: ops, source: "node" }, { omitted });
4955
5429
  }
4956
5430
  },
4957
5431
  single("list_events", "events.list", "List events of an issue", "Events of one issue, newest first, with a cursor for older ones."),
@@ -4961,9 +5435,9 @@ var MCP_TOOL_DEFS = [
4961
5435
  title: "Get a trace",
4962
5436
  description: "Summary of one distributed trace (services, duration, errors) by its 32-hex trace id, and optionally its spans (errors only, or the first page).",
4963
5437
  operations: ["traces.get", "traces.spans"],
4964
- input: z29.object({
5438
+ input: z32.object({
4965
5439
  trace_id: traceIdSchema.describe("W3C trace id, 32 hex characters."),
4966
- spans: z29.enum(["none", "errors", "all"]).default("none")
5440
+ spans: z32.enum(["none", "errors", "all"]).default("none")
4967
5441
  }),
4968
5442
  async run(args, rt) {
4969
5443
  const sum = await rt.call("traces.get", { trace_id: args["trace_id"] });
@@ -4981,7 +5455,11 @@ var MCP_TOOL_DEFS = [
4981
5455
  else
4982
5456
  omitted.push({ part: "spans", reason: r.code });
4983
5457
  }
4984
- return wrapResult({ data: { trace: sum.body, ...spans !== undefined ? { spans } : {} }, operations: ["traces.get", "traces.spans"], source: "node" }, { omitted });
5458
+ return wrapResult({
5459
+ data: { trace: sum.body, ...spans !== undefined ? { spans } : {} },
5460
+ operations: ["traces.get", "traces.spans"],
5461
+ source: "node"
5462
+ }, { omitted });
4985
5463
  }
4986
5464
  },
4987
5465
  single("search_spans", "spans.list", "Search spans", "OpenTelemetry spans in a time window (start and end required): filter by project, environment, service, operation, status, kind, duration or attribute filters (`attrs`, JSON list of {k, op, v}). mode=traces returns one row per trace."),
@@ -4991,23 +5469,29 @@ var MCP_TOOL_DEFS = [
4991
5469
  title: "Query metrics",
4992
5470
  description: "OpenTelemetry metrics of one project. Without `name`: the metric catalog (name, type, unit, series count, last seen; `q` narrows by name) and the node's series caps. With `name` plus start and end: the metric aggregated per step — `aggregation` defaults to rate for counters, p95 for histograms and avg for gauges — optionally filtered by attributes (`attrs`, JSON list of {k, op, v}) and grouped by up to two attribute keys (`group_by`, comma-separated). Exemplar trace ids open with get_trace.",
4993
5471
  operations: ["metrics.names", "metrics.query"],
4994
- input: z29.object({
4995
- project: z29.number().int().positive().describe("Numeric project id from list_projects."),
4996
- name: z29.string().regex(METRIC_NAME_RE).optional().describe("Metric name from the catalog, e.g. http.server.request.duration."),
4997
- q: z29.string().max(255).optional().describe("Catalog only: part of a metric name."),
4998
- aggregation: z29.enum(METRIC_AGGREGATIONS).optional(),
5472
+ input: z32.object({
5473
+ project: z32.number().int().positive().describe("Numeric project id from list_projects."),
5474
+ name: z32.string().regex(METRIC_NAME_RE).optional().describe("Metric name from the catalog, e.g. http.server.request.duration."),
5475
+ q: z32.string().max(255).optional().describe("Catalog only: part of a metric name."),
5476
+ aggregation: z32.enum(METRIC_AGGREGATIONS).optional(),
4999
5477
  start: isoWindow.start.optional(),
5000
5478
  end: isoWindow.end.optional(),
5001
- step: z29.number().int().min(60).max(86400).multipleOf(60).optional().describe("Seconds per point (whole minutes); picked from the window when absent."),
5002
- attrs: z29.string().max(2000).optional(),
5003
- group_by: z29.string().max(600).optional(),
5004
- environment: z29.string().max(2000).optional().describe("Comma-separated environments.")
5479
+ step: z32.number().int().min(60).max(86400).multipleOf(60).optional().describe("Seconds per point (whole minutes); picked from the window when absent."),
5480
+ attrs: z32.string().max(2000).optional(),
5481
+ group_by: z32.string().max(600).optional(),
5482
+ environment: z32.string().max(2000).optional().describe("Comma-separated environments.")
5005
5483
  }),
5006
5484
  async run(args, rt) {
5007
- const scope = { project: args["project"], ...args["environment"] ? { environment: args["environment"] } : {} };
5485
+ const scope = {
5486
+ project: args["project"],
5487
+ ...args["environment"] ? { environment: args["environment"] } : {}
5488
+ };
5008
5489
  const name = args["name"];
5009
5490
  if (!name) {
5010
- const r = await rt.call("metrics.names", { ...scope, ...args["q"] ? { q: args["q"] } : {} });
5491
+ const r = await rt.call("metrics.names", {
5492
+ ...scope,
5493
+ ...args["q"] ? { q: args["q"] } : {}
5494
+ });
5011
5495
  if (!r.ok)
5012
5496
  return errorResult(r);
5013
5497
  return wrapResult({ data: r.body, operations: ["metrics.names"], source: "node" }, listExtra(r.body));
@@ -5022,7 +5506,12 @@ var MCP_TOOL_DEFS = [
5022
5506
  const rows = cat.body?.names ?? [];
5023
5507
  const kind = rows.find((n) => n.name === name)?.kind;
5024
5508
  if (!METRIC_KINDS.includes(kind))
5025
- return errorResult({ ok: false, status: 404, code: "NOT_FOUND", detail: "unknown_metric" });
5509
+ return errorResult({
5510
+ ok: false,
5511
+ status: 404,
5512
+ code: "NOT_FOUND",
5513
+ detail: "unknown_metric"
5514
+ });
5026
5515
  aggregation = defaultAggregation(kind);
5027
5516
  }
5028
5517
  const r = await rt.call("metrics.query", {
@@ -5040,23 +5529,65 @@ var MCP_TOOL_DEFS = [
5040
5529
  return wrapResult({ data: r.body, operations: ops, source: "node" }, listExtra(r.body));
5041
5530
  }
5042
5531
  },
5532
+ {
5533
+ ...spec("release_health"),
5534
+ title: "Release health",
5535
+ description: "What changed with a release (spec 13). With `version`: that release in one environment against the previous one (or `compare`) — three lists for its first 24 hours: new issues, regressed issues and increased issues (≥ 2× events per hour and ≥ 10 events), up to 50 each with hourly sparklines, plus its deploy markers. Without `version`: the project's releases, newest deploy first, with those three counts. `environment` defaults to production (else the busiest). Whether a resolved issue is really fixed: get_issue returns its fix status.",
5536
+ operations: ["releases.list", "releases.health"],
5537
+ input: z32.object({
5538
+ project: z32.number().int().positive().describe("Numeric project id from list_projects."),
5539
+ version: releaseNameSchema.optional().describe("Release name exactly as the SDK sends it, e.g. web@1.4.2."),
5540
+ environment: environmentNameSchema.optional().describe("One environment, e.g. production."),
5541
+ compare: releaseNameSchema.optional().describe("With version: compare against this release instead of the previous one.")
5542
+ }),
5543
+ async run(args, rt) {
5544
+ const scope = {
5545
+ project: args["project"],
5546
+ ...args["environment"] ? { environment: args["environment"] } : {}
5547
+ };
5548
+ const version = args["version"];
5549
+ if (!version) {
5550
+ const r = await rt.call("releases.list", scope);
5551
+ if (!r.ok)
5552
+ return errorResult(r);
5553
+ return wrapResult({ data: r.body, operations: ["releases.list"], source: "node" });
5554
+ }
5555
+ const r = await rt.call("releases.health", {
5556
+ ...scope,
5557
+ version,
5558
+ ...args["compare"] ? { compare: args["compare"] } : {}
5559
+ });
5560
+ if (!r.ok)
5561
+ return errorResult(r);
5562
+ return wrapResult({ data: r.body, operations: ["releases.health"], source: "node" });
5563
+ }
5564
+ },
5043
5565
  {
5044
5566
  ...spec("correlate"),
5045
5567
  title: "Correlate by trace or run",
5046
5568
  description: "Everything that shares one W3C trace id or one Belvador run id (`belvador.run.id`, set by job monitors) in a time window: the trace summary, its error spans and the logs. Give exactly one of trace_id or run_id.",
5047
5569
  operations: ["traces.get", "traces.spans", "spans.list", "logs.list"],
5048
- input: z29.object({
5570
+ input: z32.object({
5049
5571
  trace_id: traceIdSchema.optional(),
5050
- run_id: z29.string().min(1).max(128).optional(),
5572
+ run_id: z32.string().min(1).max(128).optional(),
5051
5573
  ...isoWindow,
5052
- project: z29.string().max(2000).optional().describe("Comma-separated project ids.")
5574
+ project: z32.string().max(2000).optional().describe("Comma-separated project ids.")
5053
5575
  }),
5054
5576
  async run(args, rt) {
5055
5577
  const trace = args["trace_id"];
5056
5578
  const run = args["run_id"];
5057
5579
  if (!!trace === !!run)
5058
- return errorResult({ ok: false, status: 400, code: "INVALID_INPUT", detail: "one_of_trace_id_or_run_id" });
5059
- const window = { start: args["start"], end: args["end"], ...args["project"] ? { project: args["project"] } : {} };
5580
+ return errorResult({
5581
+ ok: false,
5582
+ status: 400,
5583
+ code: "INVALID_INPUT",
5584
+ detail: "one_of_trace_id_or_run_id"
5585
+ });
5586
+ const window = {
5587
+ start: args["start"],
5588
+ end: args["end"],
5589
+ ...args["project"] ? { project: args["project"] } : {}
5590
+ };
5060
5591
  const attrs = run ? JSON.stringify([{ k: "belvador.run.id", op: "=", v: run }]) : undefined;
5061
5592
  const omitted = [];
5062
5593
  const data = {};
@@ -5065,7 +5596,12 @@ var MCP_TOOL_DEFS = [
5065
5596
  const none = Promise.resolve(null);
5066
5597
  const [t, s, l] = await Promise.all([
5067
5598
  trace && has(rt, "traces.get") ? rt.call("traces.get", { trace_id: trace }) : none,
5068
- has(rt, spansOp) ? trace ? rt.call("traces.spans", { trace_id: trace, errors_only: "1", start: args["start"], end: args["end"] }) : rt.call("spans.list", { ...window, status: "error", attrs }) : none,
5599
+ has(rt, spansOp) ? trace ? rt.call("traces.spans", {
5600
+ trace_id: trace,
5601
+ errors_only: "1",
5602
+ start: args["start"],
5603
+ end: args["end"]
5604
+ }) : rt.call("spans.list", { ...window, status: "error", attrs }) : none,
5069
5605
  has(rt, "logs.list") ? rt.call("logs.list", { ...window, ...trace ? { trace_id: trace } : { attrs } }) : none
5070
5606
  ]);
5071
5607
  const windowError = [s, l].find((r) => r && !r.ok && (r.code === "QUERY_WINDOW_REQUIRED" || r.code === "QUERY_WINDOW_TOO_LARGE"));
@@ -5094,10 +5630,10 @@ var MCP_TOOL_DEFS = [
5094
5630
  title: "List monitors",
5095
5631
  description: "Monitors (cron, heartbeat, count, assertion, deadline, progress), uptime checks and SLOs with their current status. `kind` narrows to one family; `project_id` to one project (cron and uptime).",
5096
5632
  operations: ["monitors.list", "uptime.list", "slos.list"],
5097
- input: z29.object({
5098
- kind: z29.enum(["all", "cron", "uptime", "slo"]).default("all"),
5099
- project_id: z29.number().int().positive().optional(),
5100
- limit: z29.number().int().min(1).max(200).default(50)
5633
+ input: z32.object({
5634
+ kind: z32.enum(["all", "cron", "uptime", "slo"]).default("all"),
5635
+ project_id: z32.number().int().positive().optional(),
5636
+ limit: z32.number().int().min(1).max(200).default(50)
5101
5637
  }),
5102
5638
  async run(args, rt) {
5103
5639
  const kinds = args["kind"] && args["kind"] !== "all" ? [args["kind"]] : ["cron", "uptime", "slo"];
@@ -5124,11 +5660,18 @@ var MCP_TOOL_DEFS = [
5124
5660
  ...spec("get_monitor_status"),
5125
5661
  title: "Get a monitor",
5126
5662
  description: "One monitor (any type), uptime check or SLO by id: settings, current status and recent results. For count, assertion, deadline and progress monitors it adds the last 24 h of minute counts or runs from the node, and for deadline monitors the newest occurrences. `backtest: true` (count/assertion only) also replays the current settings over the last 30 days: how often it would have alerted.",
5127
- operations: ["monitors.get", "uptime.get", "slos.get", "monitors.signal", "monitors.occurrences", "monitors.backtest"],
5128
- input: z29.object({
5129
- kind: z29.enum(["cron", "uptime", "slo"]),
5130
- id: z29.guid(),
5131
- backtest: z29.boolean().default(false)
5663
+ operations: [
5664
+ "monitors.get",
5665
+ "uptime.get",
5666
+ "slos.get",
5667
+ "monitors.signal",
5668
+ "monitors.occurrences",
5669
+ "monitors.backtest"
5670
+ ],
5671
+ input: z32.object({
5672
+ kind: z32.enum(["cron", "uptime", "slo"]),
5673
+ id: z32.guid(),
5674
+ backtest: z32.boolean().default(false)
5132
5675
  }),
5133
5676
  async run(args, rt) {
5134
5677
  const k = MONITOR_KINDS2[args["kind"]];
@@ -5172,7 +5715,11 @@ var MCP_TOOL_DEFS = [
5172
5715
  else
5173
5716
  omitted.push({ part, reason: a.code });
5174
5717
  }
5175
- return wrapResult({ data, operations: ops, source: omitted.length === parts.length ? "control_plane" : "node" }, { omitted });
5718
+ return wrapResult({
5719
+ data,
5720
+ operations: ops,
5721
+ source: omitted.length === parts.length ? "control_plane" : "node"
5722
+ }, { omitted });
5176
5723
  }
5177
5724
  },
5178
5725
  single("list_alerts", "alerts.list", "List alerts", "Alerts Belvador raised (open, resolved or all), newest first, optionally for one monitor."),
@@ -5184,15 +5731,19 @@ var MCP_TOOL_DEFS = [
5184
5731
  title: "Send a test event",
5185
5732
  description: "Asks the node to send one tagged test error through the public intake of a project, proving the path real errors take. Not read-only: it creates one test event (reuse idempotency_key to retry without a second one).",
5186
5733
  operations: ["projects.send_test_event"],
5187
- input: z29.object({
5188
- project_id: z29.number().int().positive(),
5189
- idempotency_key: z29.string().min(8).max(255).optional()
5734
+ input: z32.object({
5735
+ project_id: z32.number().int().positive(),
5736
+ idempotency_key: z32.string().min(8).max(255).optional()
5190
5737
  }),
5191
5738
  async run(args, rt) {
5192
5739
  const r = await rt.call("projects.send_test_event", { project_id: args["project_id"] }, { idempotencyKey: args["idempotency_key"] ?? rt.newKey() });
5193
5740
  if (!r.ok)
5194
5741
  return errorResult(r);
5195
- return wrapResult({ data: r.body, operations: ["projects.send_test_event"], source: "control_plane" });
5742
+ return wrapResult({
5743
+ data: r.body,
5744
+ operations: ["projects.send_test_event"],
5745
+ source: "control_plane"
5746
+ });
5196
5747
  }
5197
5748
  },
5198
5749
  {
@@ -5200,9 +5751,9 @@ var MCP_TOOL_DEFS = [
5200
5751
  title: "Find a configuration change",
5201
5752
  description: "Searches what this token can change in its Belvador workspace: projects, keys and tokens, monitors of every type, maintenance windows, occurrences, uptime checks, SLOs, alert rules and destinations, members, service accounts and the node. Returns operation ids for describe_operation and plan_change, whether a person must approve the change, and whether this token holds the scope.",
5202
5753
  operations: [],
5203
- input: z29.object({
5204
- query: z29.string().min(1).max(200).describe("Words such as `rotate dsn key`, `heartbeat monitor`, `slack alert`."),
5205
- limit: z29.number().int().min(1).max(20).default(10)
5754
+ input: z32.object({
5755
+ query: z32.string().min(1).max(200).describe("Words such as `rotate dsn key`, `heartbeat monitor`, `slack alert`."),
5756
+ limit: z32.number().int().min(1).max(20).default(10)
5206
5757
  }),
5207
5758
  async run(args, rt) {
5208
5759
  const q = words(String(args["query"]));
@@ -5230,7 +5781,7 @@ var MCP_TOOL_DEFS = [
5230
5781
  title: "Describe a configuration change",
5231
5782
  description: "Everything needed to call one operation: its fields (JSON Schema, wire names), the scope, whether it needs If-Match (call plan_change for the current ETag), an idempotency key, or a person's approval, and which fields the approving person types on belvador.dev instead of the agent.",
5232
5783
  operations: [],
5233
- input: z29.object({ operation_id: operationIdArg }),
5784
+ input: z32.object({ operation_id: operationIdArg }),
5234
5785
  async run(args, rt) {
5235
5786
  const op = configureOp(args["operation_id"]);
5236
5787
  if (!op || op.method === "GET")
@@ -5259,7 +5810,7 @@ var MCP_TOOL_DEFS = [
5259
5810
  title: "Check a change before applying it",
5260
5811
  description: "Validates params for one operation without changing anything: field errors, missing scope, whether a person must approve, and — when the resource can be read — its current state, the fields that would change and the ETag to pass as if_match.",
5261
5812
  operations: [],
5262
- input: z29.object({ operation_id: operationIdArg, params }),
5813
+ input: z32.object({ operation_id: operationIdArg, params }),
5263
5814
  async run(args, rt) {
5264
5815
  const op = configureOp(args["operation_id"]);
5265
5816
  if (!op || op.method === "GET")
@@ -5308,11 +5859,11 @@ var MCP_TOOL_DEFS = [
5308
5859
  title: "Apply a configuration change",
5309
5860
  description: "Runs one operation with params (validate first with plan_change). Always send idempotency_key: repeating a call with the same key never applies it twice. Sensitive operations answer approval_required with an approval_url a person opens on belvador.dev; nothing changes until they approve with their authenticator code.",
5310
5861
  operations: [],
5311
- input: z29.object({
5862
+ input: z32.object({
5312
5863
  operation_id: operationIdArg,
5313
5864
  params,
5314
- idempotency_key: z29.string().min(8).max(255).describe("Unique per change; reuse it to retry or to fetch the result."),
5315
- if_match: z29.string().max(200).optional().describe("ETag from plan_change, for operations that need it.")
5865
+ idempotency_key: z32.string().min(8).max(255).describe("Unique per change; reuse it to retry or to fetch the result."),
5866
+ if_match: z32.string().max(200).optional().describe("ETag from plan_change, for operations that need it.")
5316
5867
  }),
5317
5868
  async run(args, rt) {
5318
5869
  const op = configureOp(args["operation_id"]);
@@ -5321,8 +5872,15 @@ var MCP_TOOL_DEFS = [
5321
5872
  const p = args["params"] ?? {};
5322
5873
  for (const f of humanWire(op))
5323
5874
  if (f in p)
5324
- return errorResult({ ok: false, status: 400, code: "INVALID_INPUT", detail: `${f} is typed by the approving person` });
5325
- const opts = { idempotencyKey: String(args["idempotency_key"]) };
5875
+ return errorResult({
5876
+ ok: false,
5877
+ status: 400,
5878
+ code: "INVALID_INPUT",
5879
+ detail: `${f} is typed by the approving person`
5880
+ });
5881
+ const opts = {
5882
+ idempotencyKey: String(args["idempotency_key"])
5883
+ };
5326
5884
  if (typeof args["if_match"] === "string" && args["if_match"])
5327
5885
  opts.ifMatch = args["if_match"];
5328
5886
  const r = await rt.call(op.id, p, opts);
@@ -5342,7 +5900,10 @@ var MCP_TOOL_DEFS = [
5342
5900
  if (r.approval && r.approval.state === "pending") {
5343
5901
  const next = APPROVAL_SETUP_OPS.includes(op.id) ? `${NEXT_PENDING} ${NEXT_SETUP}` : NEXT_PENDING;
5344
5902
  return {
5345
- structuredContent: { status: "approval_required", approval: approvalBlock(r.approval, next) },
5903
+ structuredContent: {
5904
+ status: "approval_required",
5905
+ approval: approvalBlock(r.approval, next)
5906
+ },
5346
5907
  approval: r.approval
5347
5908
  };
5348
5909
  }
@@ -5363,7 +5924,7 @@ var MCP_TOOL_DEFS = [
5363
5924
  title: "Follow an approval",
5364
5925
  description: "State of a change waiting for a person's approval: pending, approved, executed (with the ids it produced), rejected, expired or failed (with the error code).",
5365
5926
  operations: ["approvals.get"],
5366
- input: z29.object({ approval_id: z29.guid().describe("approval_id from apply_change.") }),
5927
+ input: z32.object({ approval_id: z32.guid().describe("approval_id from apply_change.") }),
5367
5928
  async run(args, rt) {
5368
5929
  const r = await rt.call("approvals.get", { approval_id: args["approval_id"] });
5369
5930
  if (!r.ok)
@@ -5383,10 +5944,10 @@ var MCP_TOOL_DEFS = [
5383
5944
  title: "Search Belvador docs",
5384
5945
  description: "Searches the public Belvador documentation (titles and summaries) and returns the best pages with their slugs for get_doc.",
5385
5946
  operations: [],
5386
- input: z29.object({
5387
- query: z29.string().min(1).max(200),
5388
- locale: z29.enum(["en", "vi"]).default("en"),
5389
- limit: z29.number().int().min(1).max(10).default(5)
5947
+ input: z32.object({
5948
+ query: z32.string().min(1).max(200),
5949
+ locale: z32.enum(["en", "vi"]).default("en"),
5950
+ limit: z32.number().int().min(1).max(10).default(5)
5390
5951
  }),
5391
5952
  async run(args, rt) {
5392
5953
  const locale = args["locale"] ?? "en";
@@ -5402,9 +5963,9 @@ var MCP_TOOL_DEFS = [
5402
5963
  title: "Read a docs page",
5403
5964
  description: "The Markdown of one public Belvador docs page by slug (e.g. `quickstart`, `sdk/react`, `reference/api`).",
5404
5965
  operations: [],
5405
- input: z29.object({
5406
- slug: z29.string().regex(/^[a-z0-9][a-z0-9/-]{0,120}$/),
5407
- locale: z29.enum(["en", "vi"]).default("en")
5966
+ input: z32.object({
5967
+ slug: z32.string().regex(/^[a-z0-9][a-z0-9/-]{0,120}$/),
5968
+ locale: z32.enum(["en", "vi"]).default("en")
5408
5969
  }),
5409
5970
  async run(args, rt) {
5410
5971
  const locale = args["locale"] ?? "en";
@@ -5417,7 +5978,13 @@ var MCP_TOOL_DEFS = [
5417
5978
  const markdown = cut ? cleanUntrustedText(md, max).text : md;
5418
5979
  return {
5419
5980
  structuredContent: {
5420
- doc: { slug, locale, url: `https://belvador.dev/${locale}/docs/${slug}`, markdown, truncated: cut }
5981
+ doc: {
5982
+ slug,
5983
+ locale,
5984
+ url: `https://belvador.dev/${locale}/docs/${slug}`,
5985
+ markdown,
5986
+ truncated: cut
5987
+ }
5421
5988
  }
5422
5989
  };
5423
5990
  }
@@ -5435,7 +6002,13 @@ function parseDocsIndex(index) {
5435
6002
  }
5436
6003
  const m = /^- \[([^\]]+)\]\(https:\/\/belvador\.dev\/api\/public\/docs\/(en|vi)\/([a-z0-9/-]+)\):\s*(.*)$/.exec(line);
5437
6004
  if (m)
5438
- out.push({ title: m[1], slug: m[3], description: m[4], section, url: `https://belvador.dev/${m[2]}/docs/${m[3]}` });
6005
+ out.push({
6006
+ title: m[1],
6007
+ slug: m[3],
6008
+ description: m[4],
6009
+ section,
6010
+ url: `https://belvador.dev/${m[2]}/docs/${m[3]}`
6011
+ });
5439
6012
  }
5440
6013
  return out;
5441
6014
  }
@@ -5586,7 +6159,7 @@ function findToken(env = process.env, keychain = keychainToken) {
5586
6159
  }
5587
6160
 
5588
6161
  // packages/mcp/src/cli.ts
5589
- var PACKAGE_VERSION = "0.5.0";
6162
+ var PACKAGE_VERSION = "0.7.0";
5590
6163
  var HELP = `belvador-mcp ${PACKAGE_VERSION} — Belvador MCP server (stdio)
5591
6164
 
5592
6165
  Usage: npx -y @belvador/mcp [--toolsets=${MCP_DEFAULT_TOOLSETS.join(",")}]