@belvador/mcp 0.1.0 → 0.3.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 (3) hide show
  1. package/README.md +4 -0
  2. package/dist/cli.js +2186 -837
  3. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -104,6 +104,7 @@ var API_ERROR_STATUS = {
104
104
  APPROVAL_EXPIRED: 410,
105
105
  APPROVAL_REJECTED: 403,
106
106
  APPROVAL_PARAMS_MISMATCH: 409,
107
+ APPROVAL_OUTCOME_UNKNOWN: 409,
107
108
  IDEMPOTENCY_KEY_REUSED: 422,
108
109
  IDEMPOTENCY_IN_PROGRESS: 409,
109
110
  PRECONDITION_REQUIRED: 428,
@@ -177,7 +178,7 @@ function cleanUntrustedText(raw, maxBytes = MCP_LIMITS.untrustedStringMaxBytes)
177
178
  const { text, cut } = cutUtf8(escaped, maxBytes);
178
179
  return { text, cut, suspicious };
179
180
  }
180
- var MCP_TOOLS_VERSION = 1;
181
+ var MCP_TOOLS_VERSION = 3;
181
182
  var MCP_TOOLS = [
182
183
  { name: "get_workspace", toolset: "investigate", scope: "org:read", readOnly: true, destructive: false, idempotent: true },
183
184
  { name: "list_projects", toolset: "investigate", scope: "projects:read", readOnly: true, destructive: false, idempotent: true },
@@ -209,14 +210,7 @@ var MCP_TOOLS = [
209
210
  var MCP_TOOLS_PENDING = {
210
211
  query_metrics: "P14",
211
212
  release_health: "P15",
212
- list_incidents: "P9",
213
- get_incident: "P9",
214
- get_coverage: "P10",
215
- search_operations: "P7",
216
- describe_operation: "P7",
217
- plan_change: "P7",
218
- apply_change: "P7",
219
- get_operation: "P7"
213
+ get_coverage: "P10"
220
214
  };
221
215
 
222
216
  // ../src/shared/mcp/docs.ts
@@ -258,10 +252,10 @@ function docsFetcher(siteUrl, fetcher = fetch, now = () => Date.now()) {
258
252
  }
259
253
 
260
254
  // ../src/shared/mcp/server.ts
261
- import { McpServer } from "@modelcontextprotocol/server";
255
+ import { CLIENT_CAPABILITIES_META_KEY, inputRequired, McpServer } from "@modelcontextprotocol/server";
262
256
 
263
257
  // ../src/shared/contracts/mcp-tools.ts
264
- import { z as z20 } from "zod";
258
+ import { z as z24 } from "zod";
265
259
 
266
260
  // ../src/shared/contracts/api-ops/access.ts
267
261
  import { z as z3 } from "zod";
@@ -641,7 +635,16 @@ var UPTIME_TRIGGER = "uptime_problem";
641
635
  var SLO_TRIGGER = "slo_burn";
642
636
  var RULE_TRIGGERS = [...ALERT_TRIGGERS, INTEGRATION_TRIGGER, MONITOR_TRIGGER, UPTIME_TRIGGER, SLO_TRIGGER];
643
637
  var SOLO_TRIGGERS = [INTEGRATION_TRIGGER, MONITOR_TRIGGER, UPTIME_TRIGGER, SLO_TRIGGER];
644
- var MONITOR_RULE_KINDS = ["missed", "failed", "timeout", "unknown"];
638
+ var MONITOR_RULE_KINDS = [
639
+ "missed",
640
+ "failed",
641
+ "timeout",
642
+ "unknown",
643
+ "count",
644
+ "assertion",
645
+ "deadline",
646
+ "stalled"
647
+ ];
645
648
  var SLO_RULE_SEVERITIES = ["page", "ticket"];
646
649
  function validRuleTriggers(triggers) {
647
650
  if (triggers.length === 1 && SOLO_TRIGGERS.includes(triggers[0]))
@@ -662,8 +665,9 @@ var ruleInputSchema = z4.object({
662
665
  isEnabled: z4.boolean(),
663
666
  notifyAll: z4.boolean(),
664
667
  destinationIds: z4.array(z4.guid()).max(20),
665
- monitorKinds: z4.array(z4.enum(MONITOR_RULE_KINDS)).min(1).max(4).default([...MONITOR_RULE_KINDS]),
666
- sloSeverities: z4.array(z4.enum(SLO_RULE_SEVERITIES)).min(1).max(2).default([...SLO_RULE_SEVERITIES])
668
+ monitorKinds: z4.array(z4.enum(MONITOR_RULE_KINDS)).min(1).max(MONITOR_RULE_KINDS.length).default([...MONITOR_RULE_KINDS]),
669
+ sloSeverities: z4.array(z4.enum(SLO_RULE_SEVERITIES)).min(1).max(2).default([...SLO_RULE_SEVERITIES]),
670
+ policyId: z4.guid().nullable().default(null)
667
671
  });
668
672
 
669
673
  // ../src/shared/contracts/api-ops/alerts.ts
@@ -680,7 +684,7 @@ var ALERT_INPUTS = {
680
684
  destinationOnly: z5.object({ destinationId: uuid }),
681
685
  createDestination: z5.object({
682
686
  workspaceId: uuid,
683
- provider: z5.enum(["telegram", "slack", "email", "webhook"]),
687
+ provider: z5.enum(["telegram", "slack", "email", "webhook", "pagerduty", "incident_io"]),
684
688
  name,
685
689
  projectIds,
686
690
  locale
@@ -762,12 +766,14 @@ var ALERT_OPERATIONS = [
762
766
  idempotency: "required",
763
767
  status: 201,
764
768
  mcp: "configure",
765
- summary: "Start adding a Telegram, Slack, email or webhook destination; a person enters its secrets.",
769
+ summary: "Start adding a Telegram, Slack, email, webhook, PagerDuty or incident.io destination; a person enters its secrets.",
766
770
  ui: [
767
771
  "alerts#createSlackDestination",
768
772
  "alerts#createWebhookDestination",
769
773
  "alerts#createTelegramDestination",
770
- "alerts#createEmailDestination"
774
+ "alerts#createEmailDestination",
775
+ "alerts#createPagerDutyDestination",
776
+ "alerts#createIncidentIoDestination"
771
777
  ]
772
778
  }),
773
779
  op({
@@ -856,17 +862,78 @@ var ALERT_OPERATIONS = [
856
862
  })
857
863
  ];
858
864
 
859
- // ../src/shared/contracts/api-ops/monitors.ts
860
- import { z as z11 } from "zod";
865
+ // ../src/shared/contracts/api-ops/incidents.ts
866
+ import { z as z10 } from "zod";
861
867
 
862
- // ../src/shared/contracts/heartbeat.ts
868
+ // ../src/shared/contracts/notifications.ts
869
+ import { z as z9 } from "zod";
870
+
871
+ // ../src/shared/contracts/maintenance.ts
872
+ import { z as z6 } from "zod";
873
+ var MAINTENANCE_SCOPES = ["workspace", "project", "monitor"];
874
+ var MAINTENANCE_LIMITS = {
875
+ durationMinutesMin: 5,
876
+ durationMinutesMax: 1440,
877
+ reasonMax: 200,
878
+ idsMax: 50,
879
+ onceAheadDays: 366,
880
+ previewStarts: 3
881
+ };
882
+ var weekdaySchema = z6.number().int().min(1).max(7);
883
+ var timeOfDay = z6.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/);
884
+ var base = {
885
+ scope: z6.enum(MAINTENANCE_SCOPES),
886
+ projectIds: z6.array(z6.number().int().positive()).max(MAINTENANCE_LIMITS.idsMax),
887
+ monitorIds: z6.array(z6.guid()).max(MAINTENANCE_LIMITS.idsMax),
888
+ timezone: z6.string().trim().min(1).max(64),
889
+ durationMinutes: z6.number().int().min(MAINTENANCE_LIMITS.durationMinutesMin).max(MAINTENANCE_LIMITS.durationMinutesMax),
890
+ reason: z6.string().trim().max(MAINTENANCE_LIMITS.reasonMax).regex(/^[^\p{Cc}]*$/u)
891
+ };
892
+ var maintenanceInputSchema = z6.discriminatedUnion("kind", [
893
+ z6.object({ kind: z6.literal("once"), startsAt: z6.string().datetime({ offset: true }), ...base }),
894
+ z6.object({
895
+ kind: z6.literal("weekly"),
896
+ weekdays: z6.array(weekdaySchema).min(1).max(7),
897
+ startTime: timeOfDay,
898
+ ...base
899
+ })
900
+ ]).superRefine((w, ctx) => {
901
+ const bad = (path) => ctx.addIssue({ code: "custom", path: [path], message: "MAINTENANCE_INVALID" });
902
+ if (w.scope === "workspace" && (w.projectIds.length || w.monitorIds.length))
903
+ bad("scope");
904
+ if (w.scope === "project" && (!w.projectIds.length || w.monitorIds.length))
905
+ bad("projectIds");
906
+ if (w.scope === "monitor" && (!w.monitorIds.length || w.projectIds.length))
907
+ bad("monitorIds");
908
+ if (new Set(w.projectIds).size !== w.projectIds.length)
909
+ bad("projectIds");
910
+ if (new Set(w.monitorIds).size !== w.monitorIds.length)
911
+ bad("monitorIds");
912
+ if (w.kind === "weekly" && new Set(w.weekdays).size !== w.weekdays.length)
913
+ bad("weekdays");
914
+ if (!validTimeZone(w.timezone))
915
+ bad("timezone");
916
+ });
917
+ function validTimeZone(tz) {
918
+ try {
919
+ new Intl.DateTimeFormat("en-US", { timeZone: tz });
920
+ return true;
921
+ } catch {
922
+ return false;
923
+ }
924
+ }
925
+ var fmtCache = new Map;
926
+
927
+ // ../src/shared/contracts/signal-monitors.ts
863
928
  import { z as z8 } from "zod";
864
929
 
865
930
  // ../src/shared/contracts/monitors.ts
866
- import { z as z6 } from "zod";
931
+ import { z as z7 } from "zod";
867
932
 
868
933
  // ../src/shared/contracts/vocab/monitors.ts
869
934
  var MONITOR_MODES = ["check_in", "heartbeat"];
935
+ var MONITOR_TYPES = ["job", "count", "assertion", "deadline", "progress"];
936
+ var SIGNAL_MONITOR_TYPES = ["count", "assertion", "deadline", "progress"];
870
937
 
871
938
  // ../src/shared/contracts/monitors.ts
872
939
  var MONITOR_KINDS = ["crontab", "interval", "on_demand"];
@@ -876,8 +943,13 @@ var MONITOR_INCIDENT_CODES = [
876
943
  "MONITOR_MISSED",
877
944
  "MONITOR_FAILED",
878
945
  "MONITOR_TIMEOUT",
879
- "MONITOR_UNKNOWN"
946
+ "MONITOR_UNKNOWN",
947
+ "MONITOR_COUNT",
948
+ "MONITOR_ASSERTION",
949
+ "MONITOR_DEADLINE_MISSED",
950
+ "MONITOR_STALLED"
880
951
  ];
952
+ var FAILURE_INCIDENT_CODES = MONITOR_INCIDENT_CODES.filter((c) => c !== "MONITOR_UNKNOWN");
881
953
  var INCIDENT_EVENTS = ["opened", "updated", "resolved"];
882
954
  var UNOBSERVABLE_REASONS = [
883
955
  "node_offline",
@@ -928,100 +1000,112 @@ function crontabShapeOk(value) {
928
1000
  const fields = value.trim().split(/\s+/);
929
1001
  return value.length <= 120 && fields.length === 5 && fields.every((f) => /^[0-9A-Za-z*,/?#LW-]+$/.test(f));
930
1002
  }
931
- var crontabScheduleSchema = z6.object({
932
- type: z6.literal("crontab"),
933
- value: z6.string().refine(crontabShapeOk, "crontab")
1003
+ var crontabScheduleSchema = z7.object({
1004
+ type: z7.literal("crontab"),
1005
+ value: z7.string().refine(crontabShapeOk, "crontab")
934
1006
  });
935
- var intervalScheduleSchema = z6.object({
936
- type: z6.literal("interval"),
937
- value: z6.number().int().min(1).max(MONITOR_LIMITS.intervalValueMax),
938
- unit: z6.enum(INTERVAL_UNITS)
1007
+ var intervalScheduleSchema = z7.object({
1008
+ type: z7.literal("interval"),
1009
+ value: z7.number().int().min(1).max(MONITOR_LIMITS.intervalValueMax),
1010
+ unit: z7.enum(INTERVAL_UNITS)
939
1011
  });
940
- var scheduleSchema = z6.discriminatedUnion("type", [
1012
+ var scheduleSchema = z7.discriminatedUnion("type", [
941
1013
  crontabScheduleSchema,
942
1014
  intervalScheduleSchema
943
1015
  ]);
944
- var monitorSettingsSchema = z6.object({
1016
+ var monitorSettingsSchema = z7.object({
945
1017
  schedule: scheduleSchema.nullable(),
946
- timezone: z6.string().min(1).max(64),
947
- checkin_margin: z6.number().int().min(MONITOR_LIMITS.checkinMarginMin).max(MONITOR_LIMITS.checkinMarginMax),
948
- max_runtime: z6.number().int().min(MONITOR_LIMITS.maxRuntimeMin).max(MONITOR_LIMITS.maxRuntimeMax),
949
- failure_issue_threshold: z6.number().int().min(MONITOR_LIMITS.thresholdMin).max(MONITOR_LIMITS.thresholdMax),
950
- recovery_threshold: z6.number().int().min(MONITOR_LIMITS.thresholdMin).max(MONITOR_LIMITS.thresholdMax)
951
- });
952
- var iso = z6.string().datetime();
953
- var projectId2 = z6.number().int().positive();
954
- var envName = z6.string().min(1).max(MONITOR_LIMITS.environmentMax);
1018
+ timezone: z7.string().min(1).max(64),
1019
+ checkin_margin: z7.number().int().min(MONITOR_LIMITS.checkinMarginMin).max(MONITOR_LIMITS.checkinMarginMax),
1020
+ max_runtime: z7.number().int().min(MONITOR_LIMITS.maxRuntimeMin).max(MONITOR_LIMITS.maxRuntimeMax),
1021
+ failure_issue_threshold: z7.number().int().min(MONITOR_LIMITS.thresholdMin).max(MONITOR_LIMITS.thresholdMax),
1022
+ recovery_threshold: z7.number().int().min(MONITOR_LIMITS.thresholdMin).max(MONITOR_LIMITS.thresholdMax)
1023
+ });
1024
+ var iso = z7.string().datetime();
1025
+ var projectId2 = z7.number().int().positive();
1026
+ var envName = z7.string().min(1).max(MONITOR_LIMITS.environmentMax);
955
1027
  var monitorDefinitionSchema = monitorSettingsSchema.extend({
956
- id: z6.guid(),
1028
+ id: z7.guid(),
957
1029
  project_id: projectId2,
958
- slug: z6.string().regex(SLUG_RE),
959
- kind: z6.enum(MONITOR_KINDS),
960
- expected_environments: z6.array(envName).max(MONITOR_LIMITS.expectedEnvironmentsMax),
1030
+ slug: z7.string().regex(SLUG_RE),
1031
+ kind: z7.enum(MONITOR_KINDS),
1032
+ expected_environments: z7.array(envName).max(MONITOR_LIMITS.expectedEnvironmentsMax),
961
1033
  paused_until: iso.nullable(),
962
1034
  created_at: iso,
963
- config_source: z6.enum(CONFIG_SOURCES),
964
- config_hash: z6.string().regex(/^[0-9a-f]{64}$/).nullable()
965
- });
966
- var outcomeCounts = z6.object({
967
- ok: z6.number().int().nonnegative(),
968
- skipped: z6.number().int().nonnegative(),
969
- error: z6.number().int().nonnegative(),
970
- timeout: z6.number().int().nonnegative(),
971
- missed: z6.number().int().nonnegative(),
972
- unknown: z6.number().int().nonnegative()
973
- });
974
- var monitorStatusSchema = z6.object({
975
- monitor_id: z6.guid(),
1035
+ config_source: z7.enum(CONFIG_SOURCES),
1036
+ config_hash: z7.string().regex(/^[0-9a-f]{64}$/).nullable()
1037
+ });
1038
+ var outcomeCounts = z7.object({
1039
+ ok: z7.number().int().nonnegative(),
1040
+ skipped: z7.number().int().nonnegative(),
1041
+ error: z7.number().int().nonnegative(),
1042
+ timeout: z7.number().int().nonnegative(),
1043
+ missed: z7.number().int().nonnegative(),
1044
+ unknown: z7.number().int().nonnegative()
1045
+ });
1046
+ var signalStatusSchema = z7.object({
1047
+ type: z7.enum(SIGNAL_MONITOR_TYPES),
1048
+ value: z7.number().int().nonnegative().max(1e9).nullable(),
1049
+ threshold: z7.number().int().nonnegative().max(1e9).nullable(),
1050
+ window_end: iso.nullable(),
1051
+ pending: z7.number().int().nonnegative().max(1e6).nullable(),
1052
+ stalled: z7.number().int().nonnegative().max(1e6).nullable(),
1053
+ refused_24h: z7.number().int().nonnegative().max(1e9).nullable()
1054
+ });
1055
+ var monitorStatusSchema = z7.object({
1056
+ monitor_id: z7.guid(),
976
1057
  project_id: projectId2,
977
1058
  environment: envName,
978
- open_failure: z6.enum(["MONITOR_MISSED", "MONITOR_FAILED", "MONITOR_TIMEOUT"]).nullable(),
979
- open_unknown: z6.boolean(),
980
- unobservable: z6.enum(UNOBSERVABLE_REASONS).nullable(),
981
- last_outcome: z6.enum(RUN_OUTCOMES).nullable(),
1059
+ open_failure: z7.enum(FAILURE_INCIDENT_CODES).nullable(),
1060
+ open_unknown: z7.boolean(),
1061
+ unobservable: z7.enum(UNOBSERVABLE_REASONS).nullable(),
1062
+ last_outcome: z7.enum(RUN_OUTCOMES).nullable(),
982
1063
  last_check_in_at: iso.nullable(),
983
1064
  last_healthy_at: iso.nullable(),
984
1065
  next_deadline_at: iso.nullable(),
985
1066
  next_due_at: iso.nullable().optional(),
986
- in_progress: z6.boolean(),
1067
+ in_progress: z7.boolean(),
987
1068
  counts_24h: outcomeCounts,
1069
+ signal: signalStatusSchema.optional(),
988
1070
  evaluated_at: iso
989
1071
  });
990
- var monitorIncidentSchema = z6.object({
991
- incident_id: z6.guid(),
992
- monitor_id: z6.guid(),
1072
+ var monitorIncidentSchema = z7.object({
1073
+ incident_id: z7.guid(),
1074
+ monitor_id: z7.guid(),
993
1075
  project_id: projectId2,
994
1076
  environment: envName,
995
- code: z6.enum(MONITOR_INCIDENT_CODES),
996
- event: z6.enum(INCIDENT_EVENTS),
1077
+ code: z7.enum(MONITOR_INCIDENT_CODES),
1078
+ event: z7.enum(INCIDENT_EVENTS),
997
1079
  occurred_at: iso,
998
- detected_late: z6.boolean(),
999
- reason: z6.string().regex(REASON_RE).nullable(),
1000
- duration_ms: z6.number().int().nonnegative().nullable(),
1001
- consecutive: z6.number().int().min(1).max(1e5),
1002
- reviewed_by: z6.guid().nullable()
1080
+ detected_late: z7.boolean(),
1081
+ reason: z7.string().regex(REASON_RE).nullable(),
1082
+ duration_ms: z7.number().int().nonnegative().nullable(),
1083
+ consecutive: z7.number().int().min(1).max(1e5),
1084
+ reviewed_by: z7.guid().nullable(),
1085
+ observed: z7.number().int().min(0).max(1e9).nullable().optional(),
1086
+ threshold: z7.number().int().min(0).max(1e9).nullable().optional()
1003
1087
  });
1004
- var monitorDiscoverySchema = z6.object({
1088
+ var monitorDiscoverySchema = z7.object({
1005
1089
  project_id: projectId2,
1006
- slug: z6.string().regex(SLUG_RE),
1090
+ slug: z7.string().regex(SLUG_RE),
1007
1091
  settings: monitorSettingsSchema.nullable(),
1008
- config_hash: z6.string().regex(/^[0-9a-f]{64}$/).nullable(),
1009
- check_ins: z6.number().int().nonnegative(),
1092
+ config_hash: z7.string().regex(/^[0-9a-f]{64}$/).nullable(),
1093
+ check_ins: z7.number().int().nonnegative(),
1010
1094
  last_seen_at: iso
1011
1095
  });
1012
1096
  var MONITOR_NAME_MAX = MONITOR_LIMITS.nameMax;
1013
- var environmentName = z6.string().trim().min(1).max(MONITOR_LIMITS.environmentMax).regex(/^[A-Za-z0-9._-]+$/);
1014
- var monitorInputSchema = z6.object({
1015
- name: z6.string().trim().min(1).max(MONITOR_LIMITS.nameMax),
1016
- mode: z6.enum(MONITOR_MODES).default("check_in"),
1017
- kind: z6.enum(MONITOR_KINDS),
1097
+ var environmentName = z7.string().trim().min(1).max(MONITOR_LIMITS.environmentMax).regex(/^[A-Za-z0-9._-]+$/);
1098
+ var monitorInputSchema = z7.object({
1099
+ name: z7.string().trim().min(1).max(MONITOR_LIMITS.nameMax),
1100
+ mode: z7.enum(MONITOR_MODES).default("check_in"),
1101
+ kind: z7.enum(MONITOR_KINDS),
1018
1102
  schedule: scheduleSchema.nullable(),
1019
- timezone: z6.string().trim().min(1).max(64),
1020
- checkinMarginMin: z6.number().int().min(MONITOR_LIMITS.checkinMarginMin).max(MONITOR_LIMITS.checkinMarginMax),
1021
- maxRuntimeMin: z6.number().int().min(MONITOR_LIMITS.maxRuntimeMin).max(MONITOR_LIMITS.maxRuntimeMax),
1022
- failureThreshold: z6.number().int().min(MONITOR_LIMITS.thresholdMin).max(MONITOR_LIMITS.thresholdMax),
1023
- recoveryThreshold: z6.number().int().min(MONITOR_LIMITS.thresholdMin).max(MONITOR_LIMITS.thresholdMax),
1024
- expectedEnvironments: z6.array(environmentName).min(1).max(MONITOR_LIMITS.expectedEnvironmentsMax)
1103
+ timezone: z7.string().trim().min(1).max(64),
1104
+ checkinMarginMin: z7.number().int().min(MONITOR_LIMITS.checkinMarginMin).max(MONITOR_LIMITS.checkinMarginMax),
1105
+ maxRuntimeMin: z7.number().int().min(MONITOR_LIMITS.maxRuntimeMin).max(MONITOR_LIMITS.maxRuntimeMax),
1106
+ failureThreshold: z7.number().int().min(MONITOR_LIMITS.thresholdMin).max(MONITOR_LIMITS.thresholdMax),
1107
+ recoveryThreshold: z7.number().int().min(MONITOR_LIMITS.thresholdMin).max(MONITOR_LIMITS.thresholdMax),
1108
+ expectedEnvironments: z7.array(environmentName).min(1).max(MONITOR_LIMITS.expectedEnvironmentsMax)
1025
1109
  }).refine((v) => v.kind === "on_demand" ? v.schedule === null : v.schedule?.type === v.kind, {
1026
1110
  path: ["schedule"],
1027
1111
  message: "schedule"
@@ -1036,98 +1120,601 @@ var MONITOR_INPUT_DEFAULTS = {
1036
1120
  recoveryThreshold: MONITOR_LIMITS.recoveryThresholdDefault,
1037
1121
  expectedEnvironments: [DEFAULT_CHECK_IN_ENVIRONMENT]
1038
1122
  };
1039
- var runOutcome = z6.enum(RUN_OUTCOMES);
1040
- var runFlags = z6.array(z6.string().max(32)).max(16);
1041
- var monitorRunSchema = z6.object({
1042
- id: z6.number().int().positive(),
1043
- kind: z6.enum(["run", "missed"]),
1123
+ var runOutcome = z7.enum(RUN_OUTCOMES);
1124
+ var runFlags = z7.array(z7.string().max(32)).max(16);
1125
+ var monitorRunSchema = z7.object({
1126
+ id: z7.number().int().positive(),
1127
+ kind: z7.enum(["run", "missed"]),
1044
1128
  outcome: runOutcome,
1045
1129
  started_at: iso,
1046
1130
  ended_at: iso,
1047
- attempts: z6.number().int().nonnegative(),
1048
- duration_ms: z6.number().int().nonnegative().nullable(),
1049
- reason: z6.string().max(64).nullable(),
1050
- check_in_id: z6.string().max(64).nullable(),
1051
- trace_id: z6.string().max(32).nullable(),
1052
- release: z6.string().max(MONITOR_LIMITS.releaseMax).nullable(),
1131
+ attempts: z7.number().int().nonnegative(),
1132
+ duration_ms: z7.number().int().nonnegative().nullable(),
1133
+ reason: z7.string().max(64).nullable(),
1134
+ check_in_id: z7.string().max(64).nullable(),
1135
+ trace_id: z7.string().max(32).nullable(),
1136
+ release: z7.string().max(MONITOR_LIMITS.releaseMax).nullable(),
1053
1137
  flags: runFlags
1054
1138
  });
1055
- var openAttemptSchema = z6.object({
1056
- check_in_id: z6.string().max(64),
1057
- run_key: z6.string().max(64),
1058
- attempt: z6.number().int().nonnegative(),
1059
- state: z6.string().max(16),
1139
+ var openAttemptSchema = z7.object({
1140
+ check_in_id: z7.string().max(64),
1141
+ run_key: z7.string().max(64),
1142
+ attempt: z7.number().int().nonnegative(),
1143
+ state: z7.string().max(16),
1060
1144
  started_at: iso,
1061
1145
  deadline_at: iso
1062
1146
  });
1063
- var monitorRunsResponseSchema = z6.object({
1064
- open: z6.array(openAttemptSchema).max(100),
1065
- runs: z6.array(monitorRunSchema).max(MONITOR_LIMITS.runsPageSize),
1066
- next_cursor: z6.string().max(32).nullable()
1147
+ var monitorRunsResponseSchema = z7.object({
1148
+ open: z7.array(openAttemptSchema).max(100),
1149
+ runs: z7.array(monitorRunSchema).max(MONITOR_LIMITS.runsPageSize),
1150
+ next_cursor: z7.string().max(32).nullable()
1067
1151
  });
1068
- var timelineRunSchema = z6.object({
1069
- id: z6.number().int().positive(),
1070
- kind: z6.enum(["run", "missed"]),
1152
+ var timelineRunSchema = z7.object({
1153
+ id: z7.number().int().positive(),
1154
+ kind: z7.enum(["run", "missed"]),
1071
1155
  outcome: runOutcome,
1072
1156
  ended_at: iso,
1073
1157
  flags: runFlags
1074
1158
  });
1075
- var monitorTimelineResponseSchema = z6.object({
1076
- runs: z6.array(timelineRunSchema).max(MONITOR_LIMITS.timelineRuns)
1159
+ var monitorTimelineResponseSchema = z7.object({
1160
+ runs: z7.array(timelineRunSchema).max(MONITOR_LIMITS.timelineRuns)
1077
1161
  });
1078
- var monitorStripsResponseSchema = z6.object({
1079
- strips: z6.array(z6.object({
1080
- monitor_id: z6.guid(),
1162
+ var monitorStripsResponseSchema = z7.object({
1163
+ strips: z7.array(z7.object({
1164
+ monitor_id: z7.guid(),
1081
1165
  environment: envName,
1082
- runs: z6.array(timelineRunSchema).max(MONITOR_LIMITS.listStripRuns)
1166
+ runs: z7.array(timelineRunSchema).max(MONITOR_LIMITS.listStripRuns)
1083
1167
  })).max(5000)
1084
1168
  });
1085
- var monitorDiagnosticSchema = z6.object({
1086
- id: z6.string().regex(/^\d{1,19}$/),
1087
- check_in_id: z6.string().max(64).nullable(),
1088
- signal: z6.string().max(16),
1089
- exit_code: z6.number().int().min(0).max(255).nullable(),
1169
+ var monitorDiagnosticSchema = z7.object({
1170
+ id: z7.string().regex(/^\d{1,19}$/),
1171
+ check_in_id: z7.string().max(64).nullable(),
1172
+ signal: z7.string().max(16),
1173
+ exit_code: z7.number().int().min(0).max(255).nullable(),
1090
1174
  received_at: iso,
1091
- body: z6.string().max(MONITOR_LIMITS.diagnosticMaxBytes * 2)
1092
- });
1093
- var monitorDiagnosticsResponseSchema = z6.object({
1094
- diagnostics: z6.array(monitorDiagnosticSchema).max(50),
1095
- next_cursor: z6.string().regex(/^\d{1,19}$/).nullable()
1096
- });
1097
- var checkInDetailSchema = z6.object({
1098
- run_key: z6.string().max(64),
1099
- attempts: z6.array(z6.object({
1100
- check_in_id: z6.string().max(64),
1101
- attempt: z6.number().int().nonnegative(),
1102
- result: z6.string().max(16),
1175
+ body: z7.string().max(MONITOR_LIMITS.diagnosticMaxBytes * 2)
1176
+ });
1177
+ var monitorDiagnosticsResponseSchema = z7.object({
1178
+ diagnostics: z7.array(monitorDiagnosticSchema).max(50),
1179
+ next_cursor: z7.string().regex(/^\d{1,19}$/).nullable()
1180
+ });
1181
+ var checkInDetailSchema = z7.object({
1182
+ run_key: z7.string().max(64),
1183
+ attempts: z7.array(z7.object({
1184
+ check_in_id: z7.string().max(64),
1185
+ attempt: z7.number().int().nonnegative(),
1186
+ result: z7.string().max(16),
1103
1187
  started_at: iso,
1104
1188
  ended_at: iso.nullable(),
1105
- duration_ms: z6.number().int().nonnegative().nullable(),
1106
- reason: z6.string().max(64).nullable(),
1107
- trace_id: z6.string().max(32).nullable(),
1108
- release: z6.string().max(MONITOR_LIMITS.releaseMax).nullable()
1189
+ duration_ms: z7.number().int().nonnegative().nullable(),
1190
+ reason: z7.string().max(64).nullable(),
1191
+ trace_id: z7.string().max(32).nullable(),
1192
+ release: z7.string().max(MONITOR_LIMITS.releaseMax).nullable()
1109
1193
  })).max(1000),
1110
- errors: z6.array(z6.object({
1111
- event_id: z6.string().max(64),
1112
- issue_id: z6.number().int().nonnegative(),
1113
- title: z6.string().max(1024),
1114
- level: z6.string().max(16),
1194
+ errors: z7.array(z7.object({
1195
+ event_id: z7.string().max(64),
1196
+ issue_id: z7.number().int().nonnegative(),
1197
+ title: z7.string().max(1024),
1198
+ level: z7.string().max(16),
1115
1199
  timestamp: iso,
1116
- same_trace: z6.boolean()
1200
+ same_trace: z7.boolean()
1117
1201
  })).max(50),
1118
- diagnostics: z6.array(monitorDiagnosticSchema).max(20).default([])
1202
+ diagnostics: z7.array(monitorDiagnosticSchema).max(20).default([])
1119
1203
  });
1120
- var incidentReviewSchema = z6.object({ incident_id: z6.guid() });
1204
+ var incidentReviewSchema = z7.object({ incident_id: z7.guid() });
1205
+
1206
+ // ../src/shared/contracts/signal-monitors.ts
1207
+ var isSignalMonitorType = (t) => SIGNAL_MONITOR_TYPES.includes(t);
1208
+ var SIGNAL_KINDS = ["event", "check_in", "span", "log"];
1209
+ var SELECTOR_OPS = ["eq", "ne", "lt", "le", "gt", "ge", "in", "exists", "not_exists", "prefix"];
1210
+ var NUMERIC_OPS = new Set(["lt", "le", "gt", "ge"]);
1211
+ var VALUELESS_OPS = new Set(["exists", "not_exists"]);
1212
+ var COMPARATORS = ["lt", "gt", "outside"];
1213
+ var MISSING_DATA_POLICIES = ["alert", "keep", "resolve", "treat_as_zero"];
1214
+ var SEVERITIES = ["critical", "high", "medium", "low"];
1215
+ var OCCURRENCE_STATES = [
1216
+ "pending",
1217
+ "in_progress",
1218
+ "success",
1219
+ "late_success",
1220
+ "missed",
1221
+ "failed",
1222
+ "cancelled"
1223
+ ];
1224
+ var OCCURRENCE_OPEN = new Set(["pending", "in_progress"]);
1225
+ var SIGNAL_LIMITS = {
1226
+ matchMax: 5,
1227
+ assertMax: 5,
1228
+ inValuesMax: 20,
1229
+ valueMax: 256,
1230
+ keyMax: 128,
1231
+ environmentsMax: MONITOR_LIMITS.expectedEnvironmentsMax,
1232
+ windowMinutesMin: 1,
1233
+ windowMinutesMax: 1440,
1234
+ thresholdMax: 1e6,
1235
+ graceMinutesMax: 1440,
1236
+ progressMinutesMin: 1,
1237
+ progressMinutesMax: 1440,
1238
+ occurrenceIdMax: 128,
1239
+ occurrenceDueMaxDays: 35,
1240
+ lateSuccessDays: 7,
1241
+ evaluateEverySeconds: 15,
1242
+ settleSeconds: 20,
1243
+ countMaxDelayMinutes: 10,
1244
+ countMinutesPerTick: 60,
1245
+ windowsPerTick: 120,
1246
+ monitorsPerQuery: 50,
1247
+ bucketRowsPerQuery: 9000,
1248
+ backtestDays: 30,
1249
+ bucketRetentionMinutes: 2 * 1440 + 60,
1250
+ occurrencesKeptFinished: 1000,
1251
+ occurrencesPageSize: 50,
1252
+ runIdsPerQuery: 500,
1253
+ dueJudgedPerTick: 5000,
1254
+ queryMaxSeconds: 5
1255
+ };
1256
+ var SELECTOR_KEY_RE = /^(?:tags\.[A-Za-z0-9_.:-]{1,100}|[A-Za-z_][A-Za-z0-9_.:-]{0,127})$/;
1257
+ var scalar = z8.union([z8.string().max(SIGNAL_LIMITS.valueMax), z8.number().finite(), z8.boolean()]);
1258
+ var selectorConditionSchema = z8.object({
1259
+ key: z8.string().min(1).max(SIGNAL_LIMITS.keyMax).regex(SELECTOR_KEY_RE),
1260
+ op: z8.enum(SELECTOR_OPS),
1261
+ value: z8.union([scalar, z8.array(z8.string().max(SIGNAL_LIMITS.valueMax)).min(1).max(SIGNAL_LIMITS.inValuesMax)]).optional()
1262
+ }).superRefine((c, ctx) => {
1263
+ const bad = (message) => ctx.addIssue({ code: "custom", path: ["value"], message });
1264
+ if (VALUELESS_OPS.has(c.op)) {
1265
+ if (c.value !== undefined)
1266
+ bad("no_value");
1267
+ return;
1268
+ }
1269
+ if (c.value === undefined)
1270
+ return bad("value");
1271
+ if (c.op === "in") {
1272
+ if (!Array.isArray(c.value))
1273
+ bad("list");
1274
+ return;
1275
+ }
1276
+ if (Array.isArray(c.value))
1277
+ return bad("scalar");
1278
+ if (NUMERIC_OPS.has(c.op) && toNumber(c.value) === null)
1279
+ bad("number");
1280
+ if (c.op === "prefix" && (typeof c.value !== "string" || c.value.length === 0))
1281
+ bad("text");
1282
+ });
1283
+ var environmentListSchema = z8.array(z8.string().trim().min(1).max(MONITOR_LIMITS.environmentMax).regex(/^[A-Za-z0-9._-]+$/)).min(1).max(SIGNAL_LIMITS.environmentsMax).refine((v) => new Set(v).size === v.length, "unique");
1284
+ var selectorSchema = z8.object({
1285
+ signal: z8.enum(SIGNAL_KINDS),
1286
+ match: z8.array(selectorConditionSchema).max(SIGNAL_LIMITS.matchMax)
1287
+ });
1288
+ function toNumber(v) {
1289
+ if (typeof v === "number")
1290
+ return Number.isFinite(v) ? v : null;
1291
+ if (typeof v === "string" && v.trim() !== "" && v.length <= 64) {
1292
+ const n = Number(v);
1293
+ return Number.isFinite(n) ? n : null;
1294
+ }
1295
+ return null;
1296
+ }
1297
+ var minutes = (min, max) => z8.number().int().min(min).max(max);
1298
+ var threshold = z8.number().int().min(0).max(SIGNAL_LIMITS.thresholdMax);
1299
+ var recovery = z8.number().int().min(MONITOR_LIMITS.thresholdMin).max(MONITOR_LIMITS.thresholdMax);
1300
+ var common = {
1301
+ environments: environmentListSchema,
1302
+ severity: z8.enum(SEVERITIES),
1303
+ recovery_threshold: recovery
1304
+ };
1305
+ var countSettingsSchema = z8.object({
1306
+ type: z8.literal("count"),
1307
+ selector: selectorSchema,
1308
+ window_minutes: minutes(SIGNAL_LIMITS.windowMinutesMin, SIGNAL_LIMITS.windowMinutesMax),
1309
+ comparator: z8.enum(COMPARATORS),
1310
+ threshold,
1311
+ threshold_high: threshold.nullable(),
1312
+ missing_data: z8.enum(MISSING_DATA_POLICIES),
1313
+ ...common
1314
+ }).superRefine((s, ctx) => {
1315
+ if (s.comparator === "outside" && (s.threshold_high === null || s.threshold_high <= s.threshold)) {
1316
+ ctx.addIssue({ code: "custom", path: ["threshold_high"], message: "threshold_high" });
1317
+ }
1318
+ if (s.comparator !== "outside" && s.threshold_high !== null) {
1319
+ ctx.addIssue({ code: "custom", path: ["threshold_high"], message: "threshold_high" });
1320
+ }
1321
+ if (s.comparator === "lt" && s.threshold === 0) {
1322
+ ctx.addIssue({ code: "custom", path: ["threshold"], message: "threshold" });
1323
+ }
1324
+ });
1325
+ var assertionSettingsSchema = z8.object({
1326
+ type: z8.literal("assertion"),
1327
+ selector: selectorSchema,
1328
+ assert: z8.array(selectorConditionSchema).min(1).max(SIGNAL_LIMITS.assertMax),
1329
+ window_minutes: minutes(SIGNAL_LIMITS.windowMinutesMin, SIGNAL_LIMITS.windowMinutesMax),
1330
+ threshold: z8.number().int().min(1).max(SIGNAL_LIMITS.thresholdMax),
1331
+ missing_data: z8.enum(MISSING_DATA_POLICIES),
1332
+ ...common
1333
+ });
1334
+ var deadlineSettingsSchema = z8.object({
1335
+ type: z8.literal("deadline"),
1336
+ occurrence_grace_minutes: minutes(0, SIGNAL_LIMITS.graceMinutesMax),
1337
+ progress_timeout_minutes: minutes(SIGNAL_LIMITS.progressMinutesMin, SIGNAL_LIMITS.progressMinutesMax).nullable(),
1338
+ ...common
1339
+ });
1340
+ var progressSettingsSchema = z8.object({
1341
+ type: z8.literal("progress"),
1342
+ progress_timeout_minutes: minutes(SIGNAL_LIMITS.progressMinutesMin, SIGNAL_LIMITS.progressMinutesMax),
1343
+ ...common
1344
+ });
1345
+ var signalSettingsSchema = z8.discriminatedUnion("type", [
1346
+ countSettingsSchema,
1347
+ assertionSettingsSchema,
1348
+ deadlineSettingsSchema,
1349
+ progressSettingsSchema
1350
+ ]);
1351
+ function settingsFromRow(row) {
1352
+ if (!isSignalMonitorType(row.type) || !row.signal_settings || typeof row.signal_settings !== "object")
1353
+ return null;
1354
+ const r = signalSettingsSchema.safeParse({
1355
+ ...row.signal_settings,
1356
+ type: row.type,
1357
+ environments: [...row.expected_environments],
1358
+ severity: row.severity,
1359
+ recovery_threshold: row.recovery_threshold
1360
+ });
1361
+ return r.success ? r.data : null;
1362
+ }
1363
+ var signalMonitorInputSchema = z8.object({
1364
+ name: z8.string().trim().min(1).max(MONITOR_LIMITS.nameMax),
1365
+ settings: signalSettingsSchema
1366
+ });
1367
+ var signalMonitorDefinitionSchema = z8.object({
1368
+ id: z8.guid(),
1369
+ project_id: z8.number().int().positive(),
1370
+ slug: z8.string().regex(SLUG_RE),
1371
+ settings: signalSettingsSchema,
1372
+ paused_until: z8.string().datetime().nullable(),
1373
+ created_at: z8.string().datetime(),
1374
+ revision: z8.number().int().nonnegative()
1375
+ });
1376
+ var signalLimitsConfigSchema = z8.object({
1377
+ pending_occurrences_per_monitor: z8.number().int().min(1).max(1e6),
1378
+ pending_occurrences_per_project: z8.number().int().min(1).max(1e7)
1379
+ });
1380
+ var OCCURRENCE_ID_RE = /^[A-Za-z0-9._:-]{1,128}$/;
1381
+ var occurrenceInputSchema = z8.object({
1382
+ monitor_slug: z8.string().regex(SLUG_RE),
1383
+ occurrence_id: z8.string().regex(OCCURRENCE_ID_RE),
1384
+ due_at: z8.string().datetime({ offset: true }),
1385
+ environment: z8.string().trim().min(1).max(MONITOR_LIMITS.environmentMax).regex(/^[A-Za-z0-9._-]+$/).optional()
1386
+ });
1387
+ var occurrenceCancelSchema = occurrenceInputSchema.pick({ monitor_slug: true, occurrence_id: true, environment: true });
1388
+ var OCCURRENCE_PAST_SKEW_MS = 5 * 60000;
1389
+ var occurrenceRowSchema = z8.object({
1390
+ occurrence_id: z8.string().max(SIGNAL_LIMITS.occurrenceIdMax),
1391
+ environment: z8.string().max(MONITOR_LIMITS.environmentMax),
1392
+ state: z8.enum(OCCURRENCE_STATES),
1393
+ due_at: z8.string().datetime(),
1394
+ deadline_at: z8.string().datetime(),
1395
+ registered_at: z8.string().datetime(),
1396
+ started_at: z8.string().datetime().nullable(),
1397
+ last_signal_at: z8.string().datetime().nullable(),
1398
+ ended_at: z8.string().datetime().nullable(),
1399
+ stalled: z8.boolean()
1400
+ });
1401
+ var occurrencesResponseSchema = z8.object({
1402
+ occurrences: z8.array(occurrenceRowSchema).max(SIGNAL_LIMITS.occurrencesPageSize),
1403
+ pending: z8.number().int().nonnegative(),
1404
+ next_due_at: z8.string().datetime().nullable(),
1405
+ next_cursor: z8.string().max(64).nullable(),
1406
+ refused_24h: z8.number().int().nonnegative()
1407
+ });
1408
+ var signalSeriesSchema = z8.object({
1409
+ environment: z8.string().max(MONITOR_LIMITS.environmentMax),
1410
+ buckets: z8.array(z8.object({ minute: z8.string().datetime(), matched: z8.number().int().nonnegative(), violations: z8.number().int().nonnegative(), lossy: z8.boolean() })).max(1440),
1411
+ counted_through: z8.string().datetime().nullable()
1412
+ });
1413
+ var signalResponseSchema = z8.object({
1414
+ series: z8.array(signalSeriesSchema).max(SIGNAL_LIMITS.environmentsMax),
1415
+ runs: z8.array(z8.object({
1416
+ run_id: z8.string().max(SIGNAL_LIMITS.occurrenceIdMax),
1417
+ environment: z8.string().max(MONITOR_LIMITS.environmentMax),
1418
+ started_at: z8.string().datetime(),
1419
+ last_signal_at: z8.string().datetime(),
1420
+ stalled: z8.boolean()
1421
+ })).max(SIGNAL_LIMITS.occurrencesPageSize)
1422
+ });
1423
+ var backtestSettingsSchema = z8.union([countSettingsSchema, assertionSettingsSchema]);
1424
+ var backtestResponseSchema = z8.object({
1425
+ alerts: z8.number().int().nonnegative(),
1426
+ windows: z8.number().int().nonnegative(),
1427
+ violated_windows: z8.number().int().nonnegative(),
1428
+ first_at: z8.string().datetime().nullable(),
1429
+ last_at: z8.string().datetime().nullable(),
1430
+ days: z8.number().nonnegative(),
1431
+ matched_total: z8.number().int().nonnegative(),
1432
+ violations_total: z8.number().int().nonnegative()
1433
+ });
1434
+
1435
+ // ../src/shared/contracts/notifications.ts
1436
+ var NOTIFY_LIMITS = {
1437
+ policiesMax: 20,
1438
+ nameMax: 80,
1439
+ chainMax: 5,
1440
+ escalateMinutesMin: 5,
1441
+ escalateMinutesMax: 240,
1442
+ digestRowsMax: 50,
1443
+ slotSearchDays: 8
1444
+ };
1445
+ var HOLDABLE_SEVERITIES = ["medium", "low"];
1446
+ var DIGEST_MODES = ["off", "hourly", "daily"];
1447
+ var timeOfDay2 = z9.string().regex(/^([01]\d|2[0-3]):[0-5]\d$/);
1448
+ var unique = (xs) => new Set(xs).size === xs.length;
1449
+ var quietHoursSchema = z9.object({
1450
+ days: z9.array(weekdaySchema).min(1).max(7).refine(unique),
1451
+ start: timeOfDay2,
1452
+ end: timeOfDay2
1453
+ }).refine((q) => q.start !== q.end, { path: ["end"] });
1454
+ var policyInputSchema = z9.object({
1455
+ name: z9.string().trim().min(1).max(NOTIFY_LIMITS.nameMax).regex(/^[^\p{Cc}]*$/u),
1456
+ timezone: z9.string().trim().min(1).max(64).refine(validTimeZone),
1457
+ quietHours: quietHoursSchema.nullable(),
1458
+ quietSeverities: z9.array(z9.enum(HOLDABLE_SEVERITIES)).max(2).refine(unique),
1459
+ digest: z9.enum(DIGEST_MODES),
1460
+ digestAt: timeOfDay2.nullable(),
1461
+ digestSeverities: z9.array(z9.enum(HOLDABLE_SEVERITIES)).max(2).refine(unique),
1462
+ fallback: z9.array(z9.guid()).max(NOTIFY_LIMITS.chainMax).refine(unique),
1463
+ escalateAfterMinutes: z9.number().int().min(NOTIFY_LIMITS.escalateMinutesMin).max(NOTIFY_LIMITS.escalateMinutesMax).nullable(),
1464
+ escalation: z9.array(z9.guid()).max(NOTIFY_LIMITS.chainMax).refine(unique)
1465
+ }).superRefine((p, ctx) => {
1466
+ if (p.digest === "daily" !== (p.digestAt !== null))
1467
+ ctx.addIssue({ code: "custom", path: ["digestAt"], message: "digest_at" });
1468
+ if (p.escalateAfterMinutes !== null !== p.escalation.length > 0)
1469
+ ctx.addIssue({ code: "custom", path: ["escalation"], message: "escalation" });
1470
+ });
1471
+ var MIN = 60000;
1472
+ var HOUR = 60 * MIN;
1473
+ var DAY = 24 * HOUR;
1474
+
1475
+ // ../src/shared/contracts/api-ops/incidents.ts
1476
+ var incidentOnly = z10.object({ workspaceId: uuid, incidentId: uuid });
1477
+ var note = z10.string().trim().min(1).max(2000).regex(/^[^\u0000-\u0008\u000b\u000c\u000e-\u001f]*$/);
1478
+ var INCIDENT_KINDS = ["monitor", "uptime", "slo", "issue"];
1479
+ var INCIDENT_GROUP_BY = ["monitor", "project_env"];
1480
+ var incidentRuleInputSchema = z10.object({
1481
+ name: z10.string().trim().min(1).max(80).regex(/^[^\p{Cc}]*$/u),
1482
+ isEnabled: z10.boolean(),
1483
+ position: z10.number().int().min(0).max(1000).default(0),
1484
+ projectIds: z10.array(z10.number().int().positive()).max(50),
1485
+ environments: z10.array(z10.string().trim().min(1).max(64)).max(20),
1486
+ kinds: z10.array(z10.enum(INCIDENT_KINDS)).min(1).max(4),
1487
+ minSeverity: z10.enum(SEVERITIES),
1488
+ groupBy: z10.enum(INCIDENT_GROUP_BY),
1489
+ windowMinutes: z10.number().int().min(5).max(240),
1490
+ recoveryHoldMinutes: z10.number().int().min(0).max(1440)
1491
+ });
1492
+ var INCIDENT_INPUTS = {
1493
+ list: z10.object({
1494
+ workspaceId: uuid,
1495
+ limit: pageLimit,
1496
+ cursor,
1497
+ state: z10.enum(["active", "resolved", "all"]).default("all")
1498
+ }),
1499
+ incidentOnly,
1500
+ resolve: incidentOnly.extend({ note: note.max(500) }),
1501
+ note: incidentOnly.extend({ note }),
1502
+ update: incidentOnly.extend({
1503
+ title: z10.string().trim().min(1).max(120).regex(/^[^\p{Cc}]*$/u).optional(),
1504
+ ownerUserId: uuid.nullable().optional()
1505
+ }),
1506
+ workspace: z10.object({ workspaceId: uuid }),
1507
+ saveRule: z10.object({ workspaceId: uuid, ruleId: uuid.nullable(), input: incidentRuleInputSchema }),
1508
+ ruleOnly: z10.object({ workspaceId: uuid, ruleId: uuid }),
1509
+ savePolicy: z10.object({
1510
+ workspaceId: uuid,
1511
+ policyId: uuid.nullable(),
1512
+ isDefault: z10.boolean(),
1513
+ input: policyInputSchema
1514
+ }),
1515
+ policyOnly: z10.object({ workspaceId: uuid, policyId: uuid })
1516
+ };
1517
+ var I = INCIDENT_INPUTS;
1518
+ var w = "incidents:write";
1519
+ var INCIDENT_OPERATIONS = [
1520
+ op({
1521
+ id: "incidents.list",
1522
+ method: "GET",
1523
+ path: "/v1/incidents",
1524
+ scope: "incidents:read",
1525
+ sensitivity: "normal",
1526
+ kind: "read",
1527
+ rpcs: ["api_read_incidents"],
1528
+ input: I.list,
1529
+ workspace: true,
1530
+ idempotency: "none",
1531
+ paged: true,
1532
+ mcp: "reliability",
1533
+ summary: "Incidents (INC-n): state, severity and peak, owner, linked alert count; newest first.",
1534
+ ui: []
1535
+ }),
1536
+ op({
1537
+ id: "incidents.get",
1538
+ method: "GET",
1539
+ path: "/v1/incidents/{incident_id}",
1540
+ scope: "incidents:read",
1541
+ sensitivity: "normal",
1542
+ kind: "read",
1543
+ rpcs: ["api_read_incident"],
1544
+ input: I.incidentOnly,
1545
+ workspace: true,
1546
+ idempotency: "none",
1547
+ mcp: "reliability",
1548
+ summary: "One incident with its linked alerts, timeline (notes included) and message deliveries (`accepted` = the provider took it; only a person acknowledges).",
1549
+ ui: []
1550
+ }),
1551
+ op({
1552
+ id: "incidents.acknowledge",
1553
+ method: "POST",
1554
+ path: "/v1/incidents/{incident_id}/ack",
1555
+ scope: w,
1556
+ sensitivity: "normal",
1557
+ kind: "write",
1558
+ rpcs: ["acknowledge_incident"],
1559
+ input: I.incidentOnly,
1560
+ workspace: true,
1561
+ idempotency: "optional",
1562
+ mcp: "configure",
1563
+ summary: "Take ownership of an open incident; stops its escalation. Members and up.",
1564
+ ui: ["incidents#acknowledgeIncident"]
1565
+ }),
1566
+ op({
1567
+ id: "incidents.resolve",
1568
+ method: "POST",
1569
+ path: "/v1/incidents/{incident_id}/resolve",
1570
+ scope: w,
1571
+ sensitivity: "normal",
1572
+ kind: "write",
1573
+ rpcs: ["resolve_incident"],
1574
+ input: I.resolve,
1575
+ workspace: true,
1576
+ idempotency: "optional",
1577
+ mcp: "configure",
1578
+ summary: 'Close an incident by hand with a reason (1–500 characters); it is labelled "not verified".',
1579
+ ui: ["incidents#resolveIncident"]
1580
+ }),
1581
+ op({
1582
+ id: "incidents.note",
1583
+ method: "POST",
1584
+ path: "/v1/incidents/{incident_id}/notes",
1585
+ scope: w,
1586
+ sensitivity: "normal",
1587
+ kind: "write",
1588
+ rpcs: ["add_incident_note"],
1589
+ input: I.note,
1590
+ workspace: true,
1591
+ idempotency: "optional",
1592
+ mcp: "configure",
1593
+ summary: "Add a note to the incident timeline (plain text, ≤ 2,000 characters).",
1594
+ ui: ["incidents#addIncidentNote"]
1595
+ }),
1596
+ op({
1597
+ id: "incidents.update",
1598
+ method: "PATCH",
1599
+ path: "/v1/incidents/{incident_id}",
1600
+ scope: w,
1601
+ sensitivity: "normal",
1602
+ kind: "write",
1603
+ rpcs: ["update_incident"],
1604
+ input: I.update,
1605
+ workspace: true,
1606
+ idempotency: "none",
1607
+ mcp: "configure",
1608
+ summary: "Rename an incident or assign it to a member (`owner_user_id: null` clears it).",
1609
+ ui: ["incidents#updateIncident"]
1610
+ }),
1611
+ op({
1612
+ id: "incident_rules.list",
1613
+ method: "GET",
1614
+ path: "/v1/incident-rules",
1615
+ scope: "alerts:read",
1616
+ sensitivity: "normal",
1617
+ kind: "read",
1618
+ rpcs: ["api_read_incident_rules"],
1619
+ input: I.workspace,
1620
+ workspace: true,
1621
+ idempotency: "none",
1622
+ mcp: "investigate",
1623
+ summary: "Rules that turn alerts into incidents: match, grouping, window and recovery wait.",
1624
+ ui: []
1625
+ }),
1626
+ op({
1627
+ id: "incident_rules.save",
1628
+ method: "POST",
1629
+ path: "/v1/incident-rules",
1630
+ scope: "alerts:write",
1631
+ sensitivity: "normal",
1632
+ kind: "write",
1633
+ rpcs: ["save_incident_rule"],
1634
+ input: I.saveRule,
1635
+ workspace: true,
1636
+ idempotency: "optional",
1637
+ mcp: "configure",
1638
+ summary: "Create (`rule_id` null) or replace an incident rule. Admins.",
1639
+ ui: ["incidents#saveIncidentRule"]
1640
+ }),
1641
+ op({
1642
+ id: "incident_rules.delete",
1643
+ method: "DELETE",
1644
+ path: "/v1/incident-rules/{rule_id}",
1645
+ scope: "alerts:write",
1646
+ sensitivity: "normal",
1647
+ kind: "write",
1648
+ rpcs: ["delete_incident_rule"],
1649
+ input: I.ruleOnly,
1650
+ workspace: true,
1651
+ idempotency: "none",
1652
+ mcp: "configure",
1653
+ summary: "Delete an incident rule; open incidents stay as they are.",
1654
+ ui: ["incidents#deleteIncidentRule"]
1655
+ }),
1656
+ op({
1657
+ id: "notification_policies.list",
1658
+ method: "GET",
1659
+ path: "/v1/notification-policies",
1660
+ scope: "alerts:read",
1661
+ sensitivity: "normal",
1662
+ kind: "read",
1663
+ rpcs: ["api_read_notification_policies"],
1664
+ input: I.workspace,
1665
+ workspace: true,
1666
+ idempotency: "none",
1667
+ mcp: "investigate",
1668
+ summary: "Notification policies: quiet hours, digest, fallback chain and escalation.",
1669
+ ui: []
1670
+ }),
1671
+ op({
1672
+ id: "notification_policies.save",
1673
+ method: "POST",
1674
+ path: "/v1/notification-policies",
1675
+ scope: "alerts:write",
1676
+ sensitivity: "normal",
1677
+ kind: "write",
1678
+ rpcs: ["save_notification_policy"],
1679
+ input: I.savePolicy,
1680
+ workspace: true,
1681
+ idempotency: "optional",
1682
+ mcp: "configure",
1683
+ summary: "Create (`policy_id` null) or replace a policy. Critical and high are never held; chains use existing destinations only. Admins.",
1684
+ ui: ["incidents#saveNotificationPolicy"]
1685
+ }),
1686
+ op({
1687
+ id: "notification_policies.delete",
1688
+ method: "DELETE",
1689
+ path: "/v1/notification-policies/{policy_id}",
1690
+ scope: "alerts:write",
1691
+ sensitivity: "normal",
1692
+ kind: "write",
1693
+ rpcs: ["delete_notification_policy"],
1694
+ input: I.policyOnly,
1695
+ workspace: true,
1696
+ idempotency: "none",
1697
+ mcp: "configure",
1698
+ summary: "Delete a policy (not the default); its rules fall back to the default policy.",
1699
+ ui: ["incidents#deleteNotificationPolicy"]
1700
+ })
1701
+ ];
1702
+
1703
+ // ../src/shared/contracts/api-ops/monitors.ts
1704
+ import { z as z15 } from "zod";
1705
+
1706
+ // ../src/shared/contracts/heartbeat.ts
1707
+ import { z as z12 } from "zod";
1121
1708
 
1122
1709
  // ../src/shared/contracts/signed-message.ts
1123
- import { z as z7 } from "zod";
1124
- var nodeIdSchema = z7.guid();
1125
- var signedEnvelopeSchema = z7.object({
1710
+ import { z as z11 } from "zod";
1711
+ var nodeIdSchema = z11.guid();
1712
+ var signedEnvelopeSchema = z11.object({
1126
1713
  node_id: nodeIdSchema,
1127
- ts: z7.number().int().positive(),
1128
- nonce: z7.string().regex(/^[A-Za-z0-9_-]{16,64}$/),
1129
- payload: z7.record(z7.string(), z7.unknown()),
1130
- sig: z7.string().regex(/^[A-Za-z0-9_-]{86}$/)
1714
+ ts: z11.number().int().positive(),
1715
+ nonce: z11.string().regex(/^[A-Za-z0-9_-]{16,64}$/),
1716
+ payload: z11.record(z11.string(), z11.unknown()),
1717
+ sig: z11.string().regex(/^[A-Za-z0-9_-]{86}$/)
1131
1718
  });
1132
1719
 
1133
1720
  // ../src/shared/contracts/heartbeat.ts
@@ -1165,78 +1752,78 @@ var HEARTBEAT_LIMITS = {
1165
1752
  diagnosticsPerRun: 5
1166
1753
  };
1167
1754
  var PAUSED_FOREVER_MS = Date.parse("9999-12-31T00:00:00.000Z");
1168
- var uuid2 = z8.guid();
1169
- var ms = z8.number().int().nonnegative();
1170
- var hex64 = z8.string().regex(/^[0-9a-f]{64}$/);
1171
- var envName2 = z8.string().min(1).max(MONITOR_LIMITS.environmentMax);
1172
- var heartbeatMonitorConfigSchema = z8.object({
1755
+ var uuid2 = z12.guid();
1756
+ var ms = z12.number().int().nonnegative();
1757
+ var hex64 = z12.string().regex(/^[0-9a-f]{64}$/);
1758
+ var envName2 = z12.string().min(1).max(MONITOR_LIMITS.environmentMax);
1759
+ var heartbeatMonitorConfigSchema = z12.object({
1173
1760
  id: uuid2,
1174
- project_id: z8.number().int().positive(),
1175
- slug: z8.string().regex(SLUG_RE),
1761
+ project_id: z12.number().int().positive(),
1762
+ slug: z12.string().regex(SLUG_RE),
1176
1763
  environment: envName2,
1177
1764
  schedule: scheduleSchema,
1178
- timezone: z8.string().min(1).max(64),
1179
- grace_min: z8.number().int().min(MONITOR_LIMITS.checkinMarginMin).max(MONITOR_LIMITS.checkinMarginMax),
1180
- max_runtime_min: z8.number().int().min(MONITOR_LIMITS.maxRuntimeMin).max(MONITOR_LIMITS.maxRuntimeMax),
1181
- failure_threshold: z8.number().int().min(MONITOR_LIMITS.thresholdMin).max(MONITOR_LIMITS.thresholdMax),
1182
- recovery_threshold: z8.number().int().min(MONITOR_LIMITS.thresholdMin).max(MONITOR_LIMITS.thresholdMax),
1765
+ timezone: z12.string().min(1).max(64),
1766
+ grace_min: z12.number().int().min(MONITOR_LIMITS.checkinMarginMin).max(MONITOR_LIMITS.checkinMarginMax),
1767
+ max_runtime_min: z12.number().int().min(MONITOR_LIMITS.maxRuntimeMin).max(MONITOR_LIMITS.maxRuntimeMax),
1768
+ failure_threshold: z12.number().int().min(MONITOR_LIMITS.thresholdMin).max(MONITOR_LIMITS.thresholdMax),
1769
+ recovery_threshold: z12.number().int().min(MONITOR_LIMITS.thresholdMin).max(MONITOR_LIMITS.thresholdMax),
1183
1770
  paused_until: ms.nullable(),
1184
1771
  created_at: ms
1185
1772
  });
1186
- var heartbeatTokenConfigSchema = z8.object({
1773
+ var heartbeatTokenConfigSchema = z12.object({
1187
1774
  id: uuid2,
1188
1775
  monitor_id: uuid2,
1189
1776
  hash: hex64,
1190
1777
  expires_at: ms.nullable()
1191
1778
  });
1192
- var heartbeatSyncSchema = z8.object({
1193
- v: z8.literal(1),
1779
+ var heartbeatSyncSchema = z12.object({
1780
+ v: z12.literal(1),
1194
1781
  workspace_id: uuid2,
1195
- route: z8.string().regex(PING_ROUTE_RE),
1196
- revision: z8.number().int().positive(),
1197
- workspace_status: z8.enum(["active", "suspended", "deleting"]),
1198
- ingest_kill: z8.boolean(),
1199
- limits: z8.object({
1200
- check_in_rate_per_sec: z8.number().int().positive(),
1201
- check_in_burst: z8.number().int().positive(),
1202
- monthly_check_in_cap: z8.number().int().positive()
1203
- }),
1204
- projects: z8.array(z8.object({ id: z8.number().int().positive(), node_id: nodeIdSchema.nullable() })).max(1000),
1205
- monitors: z8.array(heartbeatMonitorConfigSchema).max(HEARTBEAT_LIMITS.maxMonitorsPerWorkspace),
1206
- tokens: z8.array(heartbeatTokenConfigSchema).max(HEARTBEAT_LIMITS.maxMonitorsPerWorkspace * 2)
1207
- });
1208
- var signedHeartbeatSyncSchema = z8.object({
1209
- body: z8.string().min(2).max(4 * 1024 * 1024),
1210
- ts: z8.number().int().positive(),
1211
- kid: z8.string().regex(/^[A-Za-z0-9_-]{1,40}$/),
1212
- sig: z8.string().regex(/^[A-Za-z0-9_-]{86}$/)
1213
- });
1214
- var heartbeatHourSchema = z8.object({
1782
+ route: z12.string().regex(PING_ROUTE_RE),
1783
+ revision: z12.number().int().positive(),
1784
+ workspace_status: z12.enum(["active", "suspended", "deleting"]),
1785
+ ingest_kill: z12.boolean(),
1786
+ limits: z12.object({
1787
+ check_in_rate_per_sec: z12.number().int().positive(),
1788
+ check_in_burst: z12.number().int().positive(),
1789
+ monthly_check_in_cap: z12.number().int().positive()
1790
+ }),
1791
+ projects: z12.array(z12.object({ id: z12.number().int().positive(), node_id: nodeIdSchema.nullable() })).max(1000),
1792
+ monitors: z12.array(heartbeatMonitorConfigSchema).max(HEARTBEAT_LIMITS.maxMonitorsPerWorkspace),
1793
+ tokens: z12.array(heartbeatTokenConfigSchema).max(HEARTBEAT_LIMITS.maxMonitorsPerWorkspace * 2)
1794
+ });
1795
+ var signedHeartbeatSyncSchema = z12.object({
1796
+ body: z12.string().min(2).max(4 * 1024 * 1024),
1797
+ ts: z12.number().int().positive(),
1798
+ kid: z12.string().regex(/^[A-Za-z0-9_-]{1,40}$/),
1799
+ sig: z12.string().regex(/^[A-Za-z0-9_-]{86}$/)
1800
+ });
1801
+ var heartbeatHourSchema = z12.object({
1215
1802
  monitor_id: uuid2,
1216
- hour: z8.string().datetime(),
1217
- ok: z8.number().int().nonnegative(),
1218
- failed: z8.number().int().nonnegative(),
1219
- started: z8.number().int().nonnegative(),
1220
- missed: z8.number().int().nonnegative(),
1221
- logs: z8.number().int().nonnegative()
1222
- });
1223
- var heartbeatReportSchema = z8.object({
1224
- v: z8.literal(1),
1803
+ hour: z12.string().datetime(),
1804
+ ok: z12.number().int().nonnegative(),
1805
+ failed: z12.number().int().nonnegative(),
1806
+ started: z12.number().int().nonnegative(),
1807
+ missed: z12.number().int().nonnegative(),
1808
+ logs: z12.number().int().nonnegative()
1809
+ });
1810
+ var heartbeatReportSchema = z12.object({
1811
+ v: z12.literal(1),
1225
1812
  workspace_id: uuid2,
1226
- route: z8.string().regex(PING_ROUTE_RE),
1227
- revision: z8.number().int().nonnegative(),
1228
- sent_at: z8.string().datetime(),
1229
- incidents: z8.array(monitorIncidentSchema).max(HEARTBEAT_LIMITS.reportMaxIncidents),
1230
- statuses: z8.array(monitorStatusSchema).max(HEARTBEAT_LIMITS.reportMaxStatuses),
1231
- hours: z8.array(heartbeatHourSchema).max(HEARTBEAT_LIMITS.reportMaxHours),
1232
- token_uses: z8.array(z8.object({ token_id: uuid2, last_used_at: z8.string().datetime() })).max(HEARTBEAT_LIMITS.maxMonitorsPerWorkspace * 2)
1813
+ route: z12.string().regex(PING_ROUTE_RE),
1814
+ revision: z12.number().int().nonnegative(),
1815
+ sent_at: z12.string().datetime(),
1816
+ incidents: z12.array(monitorIncidentSchema).max(HEARTBEAT_LIMITS.reportMaxIncidents),
1817
+ statuses: z12.array(monitorStatusSchema).max(HEARTBEAT_LIMITS.reportMaxStatuses),
1818
+ hours: z12.array(heartbeatHourSchema).max(HEARTBEAT_LIMITS.reportMaxHours),
1819
+ token_uses: z12.array(z12.object({ token_id: uuid2, last_used_at: z12.string().datetime() })).max(HEARTBEAT_LIMITS.maxMonitorsPerWorkspace * 2)
1233
1820
  });
1234
1821
  var ENCODER = new TextEncoder;
1235
1822
  var UTF8 = new TextDecoder("utf-8", { fatal: false, ignoreBOM: false });
1236
1823
  var TOKEN_IN_TEXT = new RegExp(PING_TOKEN_PATTERN, "g");
1237
1824
 
1238
1825
  // ../src/shared/contracts/slo.ts
1239
- import { z as z9 } from "zod";
1826
+ import { z as z13 } from "zod";
1240
1827
 
1241
1828
  // ../src/shared/contracts/vocab/slo.ts
1242
1829
  var SLO_SOURCES = ["uptime", "monitor", "heartbeat", "spans"];
@@ -1268,17 +1855,17 @@ var SLO_SOURCE_META = {
1268
1855
  heartbeat: { provenance: "ping_token", estimated: false, slis: ["availability"], budgeting: "Occurrences" },
1269
1856
  spans: { provenance: "ingest_key", estimated: true, slis: ["availability", "latency"], budgeting: "Occurrences" }
1270
1857
  };
1271
- var nodeSloSchema = z9.object({
1272
- slo_id: z9.guid(),
1273
- project_id: z9.number().int().positive(),
1274
- source: z9.enum(["monitor", "spans"]),
1275
- sli: z9.enum(SLO_SLIS),
1276
- monitor_id: z9.guid().optional(),
1277
- environment: z9.string().min(1).max(SLO_LIMITS.environmentMaxChars).optional(),
1278
- service: z9.string().min(1).max(128).optional(),
1279
- operation: z9.string().min(1).max(256).optional(),
1280
- latency_threshold_ms: z9.number().int().min(1).max(60000).optional(),
1281
- public_sources: z9.boolean()
1858
+ var nodeSloSchema = z13.object({
1859
+ slo_id: z13.guid(),
1860
+ project_id: z13.number().int().positive(),
1861
+ source: z13.enum(["monitor", "spans"]),
1862
+ sli: z13.enum(SLO_SLIS),
1863
+ monitor_id: z13.guid().optional(),
1864
+ environment: z13.string().min(1).max(SLO_LIMITS.environmentMaxChars).optional(),
1865
+ service: z13.string().min(1).max(128).optional(),
1866
+ operation: z13.string().min(1).max(256).optional(),
1867
+ latency_threshold_ms: z13.number().int().min(1).max(60000).optional(),
1868
+ public_sources: z13.boolean()
1282
1869
  }).superRefine((v, ctx) => {
1283
1870
  if (v.source === "monitor" && (!v.monitor_id || v.sli !== "availability"))
1284
1871
  ctx.addIssue({ code: "custom", path: ["monitor_id"], message: "INVALID_INPUT" });
@@ -1287,27 +1874,27 @@ var nodeSloSchema = z9.object({
1287
1874
  if (v.sli === "latency" !== (v.latency_threshold_ms !== undefined))
1288
1875
  ctx.addIssue({ code: "custom", path: ["latency_threshold_ms"], message: "INVALID_INPUT" });
1289
1876
  });
1290
- var sliCountsSchema = z9.object({
1291
- minute: z9.string().datetime(),
1292
- items: z9.array(z9.object({ slo_id: z9.guid(), good: z9.number().int().min(0), total: z9.number().int().min(0) }).refine((x) => x.good <= x.total, { message: "INVALID_INPUT" })).max(SLO_LIMITS.sliItemsPerMessage)
1293
- });
1294
- var sloInputSchema = z9.object({
1295
- name: z9.string().trim().min(1).max(SLO_LIMITS.nameMaxChars),
1296
- description: z9.string().max(SLO_LIMITS.descriptionMaxChars).default(""),
1297
- source: z9.enum(SLO_SOURCES),
1298
- sourceRef: z9.object({
1299
- id: z9.guid().optional(),
1300
- projectId: z9.number().int().positive().optional(),
1301
- service: z9.string().max(128).optional(),
1302
- operation: z9.string().max(256).optional(),
1303
- environment: z9.string().max(SLO_LIMITS.environmentMaxChars).optional()
1304
- }),
1305
- sli: z9.enum(SLO_SLIS),
1306
- latencyThresholdMs: z9.number().int().min(1).max(60000).nullable(),
1307
- objective: z9.number().min(SLO_LIMITS.objectiveMin).max(SLO_LIMITS.objectiveMax),
1308
- windowDays: z9.union([z9.literal(7), z9.literal(28), z9.literal(30)]),
1309
- alertPolicy: z9.enum(SLO_ALERT_POLICIES),
1310
- allowPublicSources: z9.boolean().default(false)
1877
+ var sliCountsSchema = z13.object({
1878
+ minute: z13.string().datetime(),
1879
+ items: z13.array(z13.object({ slo_id: z13.guid(), good: z13.number().int().min(0), total: z13.number().int().min(0) }).refine((x) => x.good <= x.total, { message: "INVALID_INPUT" })).max(SLO_LIMITS.sliItemsPerMessage)
1880
+ });
1881
+ var sloInputSchema = z13.object({
1882
+ name: z13.string().trim().min(1).max(SLO_LIMITS.nameMaxChars),
1883
+ description: z13.string().max(SLO_LIMITS.descriptionMaxChars).default(""),
1884
+ source: z13.enum(SLO_SOURCES),
1885
+ sourceRef: z13.object({
1886
+ id: z13.guid().optional(),
1887
+ projectId: z13.number().int().positive().optional(),
1888
+ service: z13.string().max(128).optional(),
1889
+ operation: z13.string().max(256).optional(),
1890
+ environment: z13.string().max(SLO_LIMITS.environmentMaxChars).optional()
1891
+ }),
1892
+ sli: z13.enum(SLO_SLIS),
1893
+ latencyThresholdMs: z13.number().int().min(1).max(60000).nullable(),
1894
+ objective: z13.number().min(SLO_LIMITS.objectiveMin).max(SLO_LIMITS.objectiveMax),
1895
+ windowDays: z13.union([z13.literal(7), z13.literal(28), z13.literal(30)]),
1896
+ alertPolicy: z13.enum(SLO_ALERT_POLICIES),
1897
+ allowPublicSources: z13.boolean().default(false)
1311
1898
  }).superRefine((v, ctx) => {
1312
1899
  if (!SLO_SOURCE_META[v.source].slis.includes(v.sli))
1313
1900
  ctx.addIssue({ code: "custom", path: ["sli"], message: "INVALID_INPUT" });
@@ -1322,7 +1909,7 @@ var sloInputSchema = z9.object({
1322
1909
  });
1323
1910
 
1324
1911
  // ../src/shared/contracts/uptime.ts
1325
- import { z as z10 } from "zod";
1912
+ import { z as z14 } from "zod";
1326
1913
 
1327
1914
  // ../src/shared/contracts/vocab/uptime.ts
1328
1915
  var UPTIME_STATUSES = ["up", "degraded", "down", "unknown", "paused", "pending"];
@@ -1395,51 +1982,51 @@ function isForbiddenHeader(name) {
1395
1982
  const n = name.trim().toLowerCase();
1396
1983
  return UPTIME_FORBIDDEN_HEADERS.includes(n) || n.startsWith("proxy-") || n.startsWith("sec-");
1397
1984
  }
1398
- var text = z10.string().min(1).max(UPTIME_LIMITS.assertionTextMax);
1399
- var statusRange = z10.string().regex(/^[1-5][0-9]{2}(-[1-5][0-9]{2})?$/);
1400
- var assertionSchema = z10.discriminatedUnion("type", [
1401
- z10.object({ type: z10.literal("status"), in: z10.array(statusRange).min(1).max(10) }),
1402
- z10.object({ type: z10.literal("body_contains"), value: text, case_sensitive: z10.boolean().default(true) }),
1403
- z10.object({ type: z10.literal("body_not_contains"), value: text, case_sensitive: z10.boolean().default(true) }),
1404
- z10.object({
1405
- type: z10.literal("json_pointer"),
1406
- pointer: z10.string().max(256).regex(/^(\/([^~/]|~0|~1)*)*$/),
1407
- op: z10.enum(["exists", "equals", "type"]),
1408
- value: z10.string().max(UPTIME_LIMITS.assertionTextMax).optional()
1409
- }),
1410
- z10.object({
1411
- type: z10.literal("header"),
1412
- name: z10.string().min(1).max(UPTIME_LIMITS.headerNameMax).regex(/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/),
1413
- op: z10.enum(["equals", "contains", "exists"]),
1414
- value: z10.string().max(UPTIME_LIMITS.assertionTextMax).optional()
1415
- }),
1416
- z10.object({ type: z10.literal("latency_ms"), lt: z10.number().int().min(1).max(60000) }),
1417
- z10.object({ type: z10.literal("tls_valid") })
1985
+ var text = z14.string().min(1).max(UPTIME_LIMITS.assertionTextMax);
1986
+ var statusRange = z14.string().regex(/^[1-5][0-9]{2}(-[1-5][0-9]{2})?$/);
1987
+ var assertionSchema = z14.discriminatedUnion("type", [
1988
+ z14.object({ type: z14.literal("status"), in: z14.array(statusRange).min(1).max(10) }),
1989
+ z14.object({ type: z14.literal("body_contains"), value: text, case_sensitive: z14.boolean().default(true) }),
1990
+ z14.object({ type: z14.literal("body_not_contains"), value: text, case_sensitive: z14.boolean().default(true) }),
1991
+ z14.object({
1992
+ type: z14.literal("json_pointer"),
1993
+ pointer: z14.string().max(256).regex(/^(\/([^~/]|~0|~1)*)*$/),
1994
+ op: z14.enum(["exists", "equals", "type"]),
1995
+ value: z14.string().max(UPTIME_LIMITS.assertionTextMax).optional()
1996
+ }),
1997
+ z14.object({
1998
+ type: z14.literal("header"),
1999
+ name: z14.string().min(1).max(UPTIME_LIMITS.headerNameMax).regex(/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/),
2000
+ op: z14.enum(["equals", "contains", "exists"]),
2001
+ value: z14.string().max(UPTIME_LIMITS.assertionTextMax).optional()
2002
+ }),
2003
+ z14.object({ type: z14.literal("latency_ms"), lt: z14.number().int().min(1).max(60000) }),
2004
+ z14.object({ type: z14.literal("tls_valid") })
1418
2005
  ]);
1419
- var header = z10.object({
1420
- name: z10.string().min(1).max(UPTIME_LIMITS.headerNameMax).regex(/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/),
1421
- value: z10.string().max(UPTIME_LIMITS.headerValueMax).regex(/^[^\r\n\u0000]*$/)
1422
- });
1423
- var uptimeCheckInputSchema = z10.object({
1424
- projectId: z10.number().int().positive(),
1425
- name: z10.string().trim().min(1).max(UPTIME_LIMITS.nameMaxChars),
1426
- kind: z10.enum(UPTIME_KINDS),
1427
- url: z10.string().max(UPTIME_LIMITS.urlMaxChars).nullable(),
1428
- host: z10.string().max(253).nullable(),
1429
- port: z10.number().int().min(1).max(65535).nullable(),
1430
- method: z10.enum(UPTIME_METHODS).default("GET"),
1431
- headers: z10.array(header).max(UPTIME_LIMITS.headersMax).default([]),
1432
- followRedirects: z10.boolean().default(false),
1433
- timeoutMs: z10.number().int().min(UPTIME_LIMITS.timeoutMs.min).max(UPTIME_LIMITS.timeoutMs.max),
1434
- intervalSeconds: z10.number().int().refine((n) => UPTIME_INTERVALS.includes(n)),
1435
- regions: z10.array(z10.enum(UPTIME_REGIONS)).min(UPTIME_LIMITS.minRegions).max(UPTIME_REGIONS.length),
1436
- assertions: z10.array(assertionSchema).max(UPTIME_LIMITS.assertionsMax).default([]),
1437
- failureThreshold: z10.number().int().min(1).max(5),
1438
- recoveryThreshold: z10.number().int().min(1).max(5),
1439
- certWarningDays: z10.number().int().min(1).max(60),
1440
- environment: z10.string().trim().max(64).default(""),
1441
- strictMetadata: z10.boolean().default(false),
1442
- evidenceOnFailure: z10.boolean().default(true)
2006
+ var header = z14.object({
2007
+ name: z14.string().min(1).max(UPTIME_LIMITS.headerNameMax).regex(/^[!#$%&'*+.^_`|~0-9A-Za-z-]+$/),
2008
+ value: z14.string().max(UPTIME_LIMITS.headerValueMax).regex(/^[^\r\n\u0000]*$/)
2009
+ });
2010
+ var uptimeCheckInputSchema = z14.object({
2011
+ projectId: z14.number().int().positive(),
2012
+ name: z14.string().trim().min(1).max(UPTIME_LIMITS.nameMaxChars),
2013
+ kind: z14.enum(UPTIME_KINDS),
2014
+ url: z14.string().max(UPTIME_LIMITS.urlMaxChars).nullable(),
2015
+ host: z14.string().max(253).nullable(),
2016
+ port: z14.number().int().min(1).max(65535).nullable(),
2017
+ method: z14.enum(UPTIME_METHODS).default("GET"),
2018
+ headers: z14.array(header).max(UPTIME_LIMITS.headersMax).default([]),
2019
+ followRedirects: z14.boolean().default(false),
2020
+ timeoutMs: z14.number().int().min(UPTIME_LIMITS.timeoutMs.min).max(UPTIME_LIMITS.timeoutMs.max),
2021
+ intervalSeconds: z14.number().int().refine((n) => UPTIME_INTERVALS.includes(n)),
2022
+ regions: z14.array(z14.enum(UPTIME_REGIONS)).min(UPTIME_LIMITS.minRegions).max(UPTIME_REGIONS.length),
2023
+ assertions: z14.array(assertionSchema).max(UPTIME_LIMITS.assertionsMax).default([]),
2024
+ failureThreshold: z14.number().int().min(1).max(5),
2025
+ recoveryThreshold: z14.number().int().min(1).max(5),
2026
+ certWarningDays: z14.number().int().min(1).max(60),
2027
+ environment: z14.string().trim().max(64).default(""),
2028
+ strictMetadata: z14.boolean().default(false),
2029
+ evidenceOnFailure: z14.boolean().default(true)
1443
2030
  }).superRefine((v, ctx) => {
1444
2031
  if (v.kind === "http" && !v.url)
1445
2032
  ctx.addIssue({ code: "custom", path: ["url"], message: "INVALID_INPUT" });
@@ -1450,237 +2037,243 @@ var uptimeCheckInputSchema = z10.object({
1450
2037
  if (v.headers.some((h) => isForbiddenHeader(h.name)))
1451
2038
  ctx.addIssue({ code: "custom", path: ["headers"], message: "UPTIME_HEADER_FORBIDDEN" });
1452
2039
  });
1453
- var uptimeDefinitionSchema = z10.object({
1454
- check_id: z10.guid(),
1455
- workspace_id: z10.guid(),
1456
- project_id: z10.number().int().positive(),
1457
- revision: z10.number().int().nonnegative(),
1458
- kind: z10.enum(UPTIME_KINDS),
1459
- url: z10.string().max(UPTIME_LIMITS.urlMaxChars).nullable(),
1460
- host: z10.string().max(253).nullable(),
1461
- port: z10.number().int().min(1).max(65535).nullable(),
1462
- method: z10.enum(UPTIME_METHODS),
1463
- headers: z10.array(header).max(UPTIME_LIMITS.headersMax),
1464
- follow_redirects: z10.boolean(),
1465
- timeout_ms: z10.number().int().min(UPTIME_LIMITS.timeoutMs.min).max(UPTIME_LIMITS.timeoutMs.max),
1466
- interval_seconds: z10.number().int().positive(),
1467
- regions: z10.array(z10.enum(UPTIME_REGIONS)).min(1).max(3),
1468
- assertions: z10.array(assertionSchema).max(UPTIME_LIMITS.assertionsMax),
1469
- failure_threshold: z10.number().int().min(1).max(5),
1470
- recovery_threshold: z10.number().int().min(1).max(5),
1471
- cert_warning_days: z10.number().int().min(1).max(60),
1472
- strict_metadata: z10.boolean(),
1473
- evidence_on_failure: z10.boolean(),
1474
- paused_until: z10.string().nullable(),
1475
- muted_until: z10.string().nullable()
1476
- });
1477
- var timingsSchema = z10.object({
1478
- dns_ms: z10.number().nonnegative().max(60000).nullable(),
1479
- connect_ms: z10.number().nonnegative().max(60000).nullable(),
1480
- tls_ms: z10.number().nonnegative().max(60000).nullable(),
1481
- ttfb_ms: z10.number().nonnegative().max(60000).nullable(),
1482
- download_ms: z10.number().nonnegative().max(60000).nullable(),
1483
- total_ms: z10.number().nonnegative().max(60000)
1484
- });
1485
- var probeResultSchema = z10.object({
1486
- check_id: z10.guid(),
1487
- revision: z10.number().int().nonnegative(),
1488
- slot: z10.number().int().nonnegative(),
1489
- region: z10.enum(UPTIME_REGIONS),
1490
- run_now: z10.string().max(64).optional(),
1491
- scheduled_at: z10.number().int().positive(),
1492
- started_at: z10.number().int().positive(),
1493
- outcome: z10.enum(UPTIME_OUTCOMES),
1494
- reason: z10.enum(UPTIME_REASONS).nullable(),
1495
- reason_group: z10.enum(UPTIME_REASON_GROUPS).nullable(),
1496
- status_code: z10.number().int().min(100).max(599).nullable(),
2040
+ var uptimeDefinitionSchema = z14.object({
2041
+ check_id: z14.guid(),
2042
+ workspace_id: z14.guid(),
2043
+ project_id: z14.number().int().positive(),
2044
+ revision: z14.number().int().nonnegative(),
2045
+ kind: z14.enum(UPTIME_KINDS),
2046
+ url: z14.string().max(UPTIME_LIMITS.urlMaxChars).nullable(),
2047
+ host: z14.string().max(253).nullable(),
2048
+ port: z14.number().int().min(1).max(65535).nullable(),
2049
+ method: z14.enum(UPTIME_METHODS),
2050
+ headers: z14.array(header).max(UPTIME_LIMITS.headersMax),
2051
+ follow_redirects: z14.boolean(),
2052
+ timeout_ms: z14.number().int().min(UPTIME_LIMITS.timeoutMs.min).max(UPTIME_LIMITS.timeoutMs.max),
2053
+ interval_seconds: z14.number().int().positive(),
2054
+ regions: z14.array(z14.enum(UPTIME_REGIONS)).min(1).max(3),
2055
+ assertions: z14.array(assertionSchema).max(UPTIME_LIMITS.assertionsMax),
2056
+ failure_threshold: z14.number().int().min(1).max(5),
2057
+ recovery_threshold: z14.number().int().min(1).max(5),
2058
+ cert_warning_days: z14.number().int().min(1).max(60),
2059
+ strict_metadata: z14.boolean(),
2060
+ evidence_on_failure: z14.boolean(),
2061
+ paused_until: z14.string().nullable(),
2062
+ muted_until: z14.string().nullable()
2063
+ });
2064
+ var timingsSchema = z14.object({
2065
+ dns_ms: z14.number().nonnegative().max(60000).nullable(),
2066
+ connect_ms: z14.number().nonnegative().max(60000).nullable(),
2067
+ tls_ms: z14.number().nonnegative().max(60000).nullable(),
2068
+ ttfb_ms: z14.number().nonnegative().max(60000).nullable(),
2069
+ download_ms: z14.number().nonnegative().max(60000).nullable(),
2070
+ total_ms: z14.number().nonnegative().max(60000)
2071
+ });
2072
+ var probeResultSchema = z14.object({
2073
+ check_id: z14.guid(),
2074
+ revision: z14.number().int().nonnegative(),
2075
+ slot: z14.number().int().nonnegative(),
2076
+ region: z14.enum(UPTIME_REGIONS),
2077
+ run_now: z14.string().max(64).optional(),
2078
+ scheduled_at: z14.number().int().positive(),
2079
+ started_at: z14.number().int().positive(),
2080
+ outcome: z14.enum(UPTIME_OUTCOMES),
2081
+ reason: z14.enum(UPTIME_REASONS).nullable(),
2082
+ reason_group: z14.enum(UPTIME_REASON_GROUPS).nullable(),
2083
+ status_code: z14.number().int().min(100).max(599).nullable(),
1497
2084
  timings: timingsSchema.nullable(),
1498
- ip_family: z10.enum(["v4", "v6"]).nullable(),
1499
- http_version: z10.string().max(8).nullable(),
1500
- cert_not_after: z10.number().int().positive().nullable(),
1501
- cert_issuer: z10.string().max(200).nullable(),
1502
- cert_expiring: z10.boolean(),
1503
- evidence_sealed: z10.string().max(16384).nullable()
1504
- });
1505
- var probeIdSchema = z10.string().regex(/^probe-(eu|us|ap)-[a-z0-9]{4,16}$/);
1506
- var resultBatchSchema = z10.object({
1507
- v: z10.literal(1),
2085
+ ip_family: z14.enum(["v4", "v6"]).nullable(),
2086
+ http_version: z14.string().max(8).nullable(),
2087
+ cert_not_after: z14.number().int().positive().nullable(),
2088
+ cert_issuer: z14.string().max(200).nullable(),
2089
+ cert_expiring: z14.boolean(),
2090
+ evidence_sealed: z14.string().max(16384).nullable()
2091
+ });
2092
+ var probeIdSchema = z14.string().regex(/^probe-(eu|us|ap)-[a-z0-9]{4,16}$/);
2093
+ var resultBatchSchema = z14.object({
2094
+ v: z14.literal(1),
1508
2095
  probe_id: probeIdSchema,
1509
- region: z10.enum(UPTIME_REGIONS),
1510
- version: z10.string().max(40),
1511
- sent_at: z10.number().int().positive(),
1512
- results: z10.array(probeResultSchema).max(UPTIME_LIMITS.resultsBatchMax),
1513
- stats: z10.object({ lag_p99_ms: z10.number().nonnegative(), checks_per_min: z10.number().nonnegative() })
2096
+ region: z14.enum(UPTIME_REGIONS),
2097
+ version: z14.string().max(40),
2098
+ sent_at: z14.number().int().positive(),
2099
+ results: z14.array(probeResultSchema).max(UPTIME_LIMITS.resultsBatchMax),
2100
+ stats: z14.object({ lag_p99_ms: z14.number().nonnegative(), checks_per_min: z14.number().nonnegative() })
1514
2101
  });
1515
2102
  var assignmentSchema = uptimeDefinitionSchema.omit({ workspace_id: true, paused_until: true, muted_until: true }).extend({
1516
- seal_public_key: z10.string().regex(/^[A-Za-z0-9_-]{43}$/).nullable()
1517
- });
1518
- var assignmentsSchema = z10.object({
1519
- v: z10.literal(1),
1520
- region: z10.enum(UPTIME_REGIONS),
1521
- revision: z10.number().int().nonnegative(),
1522
- issued_at: z10.number().int().positive(),
1523
- checks: z10.array(assignmentSchema).max(50000),
1524
- denied_hosts: z10.array(z10.string().max(253)).max(1e4),
1525
- run_now: z10.array(z10.object({ id: z10.string().max(64), check_id: z10.guid(), expires_at: z10.number().int() })).max(500)
1526
- });
1527
- var uuid3 = z10.guid();
1528
- var b64key = z10.string().regex(/^[A-Za-z0-9_-]{43}$/);
1529
- var iso2 = z10.string().datetime();
1530
- var uptimeSyncSchema = z10.object({
1531
- v: z10.literal(1),
2103
+ seal_public_key: z14.string().regex(/^[A-Za-z0-9_-]{43}$/).nullable()
2104
+ });
2105
+ var assignmentsSchema = z14.object({
2106
+ v: z14.literal(1),
2107
+ region: z14.enum(UPTIME_REGIONS),
2108
+ revision: z14.number().int().nonnegative(),
2109
+ issued_at: z14.number().int().positive(),
2110
+ checks: z14.array(assignmentSchema).max(50000),
2111
+ denied_hosts: z14.array(z14.string().max(253)).max(1e4),
2112
+ run_now: z14.array(z14.object({ id: z14.string().max(64), check_id: z14.guid(), expires_at: z14.number().int() })).max(500)
2113
+ });
2114
+ var uuid3 = z14.guid();
2115
+ var b64key = z14.string().regex(/^[A-Za-z0-9_-]{43}$/);
2116
+ var iso2 = z14.string().datetime();
2117
+ var uptimeSyncSchema = z14.object({
2118
+ v: z14.literal(1),
1532
2119
  workspace_id: uuid3,
1533
- revision: z10.number().int().positive(),
1534
- workspace_status: z10.enum(["active", "suspended", "deleting"]),
1535
- suspended: z10.boolean(),
1536
- checks: z10.array(uptimeDefinitionSchema).max(UPTIME_LIMITS.maxChecksPerWorkspace),
1537
- projects: z10.array(z10.object({ id: z10.number().int().positive(), node_id: z10.guid().nullable(), seal_public_key: b64key.nullable() })).max(1000)
1538
- });
1539
- var uptimeReconcileSchema = z10.object({
1540
- v: z10.literal(1),
1541
- as_of: z10.number().int().positive(),
1542
- workspace_ids: z10.array(uuid3).max(UPTIME_LIMITS.reconcileMaxWorkspaces),
1543
- heartbeat_routes: z10.array(z10.string().regex(PING_ROUTE_RE)).max(UPTIME_LIMITS.reconcileMaxWorkspaces).optional()
1544
- });
1545
- var probeDirectorySyncSchema = z10.object({
1546
- v: z10.literal(1),
1547
- revision: z10.number().int().positive(),
1548
- probes: z10.array(z10.object({ probe_id: probeIdSchema, region: z10.enum(UPTIME_REGIONS), public_key: b64key, status: z10.enum(["active", "revoked"]) })).max(30),
1549
- denied_hosts: z10.array(z10.string().min(1).max(253)).max(1e4)
1550
- });
1551
- var runNowRequestSchema = z10.object({ v: z10.literal(1), workspace_id: uuid3, check_id: uuid3, run_id: z10.string().regex(/^[A-Za-z0-9_-]{8,64}$/) });
1552
- var signedAssignmentsSchema = z10.object({ assignments: assignmentsSchema, sig: z10.string().regex(/^[A-Za-z0-9_-]{86}$/) });
1553
- var uptimeRegionStateSchema = z10.object({
1554
- region: z10.enum(UPTIME_REGIONS),
1555
- outcome: z10.enum(UPTIME_OUTCOMES),
1556
- reason: z10.enum(UPTIME_REASONS).nullable(),
1557
- status_code: z10.number().int().min(100).max(599).nullable(),
1558
- total_ms: z10.number().nonnegative().max(60000).nullable(),
2120
+ revision: z14.number().int().positive(),
2121
+ workspace_status: z14.enum(["active", "suspended", "deleting"]),
2122
+ suspended: z14.boolean(),
2123
+ checks: z14.array(uptimeDefinitionSchema).max(UPTIME_LIMITS.maxChecksPerWorkspace),
2124
+ projects: z14.array(z14.object({ id: z14.number().int().positive(), node_id: z14.guid().nullable(), seal_public_key: b64key.nullable() })).max(1000)
2125
+ });
2126
+ var uptimeReconcileSchema = z14.object({
2127
+ v: z14.literal(1),
2128
+ as_of: z14.number().int().positive(),
2129
+ workspace_ids: z14.array(uuid3).max(UPTIME_LIMITS.reconcileMaxWorkspaces),
2130
+ heartbeat_routes: z14.array(z14.string().regex(PING_ROUTE_RE)).max(UPTIME_LIMITS.reconcileMaxWorkspaces).optional()
2131
+ });
2132
+ var probeDirectorySyncSchema = z14.object({
2133
+ v: z14.literal(1),
2134
+ revision: z14.number().int().positive(),
2135
+ probes: z14.array(z14.object({ probe_id: probeIdSchema, region: z14.enum(UPTIME_REGIONS), public_key: b64key, status: z14.enum(["active", "revoked"]) })).max(30),
2136
+ denied_hosts: z14.array(z14.string().min(1).max(253)).max(1e4)
2137
+ });
2138
+ var runNowRequestSchema = z14.object({ v: z14.literal(1), workspace_id: uuid3, check_id: uuid3, run_id: z14.string().regex(/^[A-Za-z0-9_-]{8,64}$/) });
2139
+ var signedAssignmentsSchema = z14.object({ assignments: assignmentsSchema, sig: z14.string().regex(/^[A-Za-z0-9_-]{86}$/) });
2140
+ var uptimeRegionStateSchema = z14.object({
2141
+ region: z14.enum(UPTIME_REGIONS),
2142
+ outcome: z14.enum(UPTIME_OUTCOMES),
2143
+ reason: z14.enum(UPTIME_REASONS).nullable(),
2144
+ status_code: z14.number().int().min(100).max(599).nullable(),
2145
+ total_ms: z14.number().nonnegative().max(60000).nullable(),
1559
2146
  timings: timingsSchema.nullable().optional(),
1560
2147
  at: iso2
1561
2148
  });
1562
- var uptimeStatusReportSchema = z10.object({
2149
+ var uptimeStatusReportSchema = z14.object({
1563
2150
  check_id: uuid3,
1564
- revision: z10.number().int().nonnegative(),
1565
- status: z10.enum(UPTIME_STATUSES),
1566
- last_verdict: z10.enum(SLOT_VERDICTS).nullable(),
2151
+ revision: z14.number().int().nonnegative(),
2152
+ status: z14.enum(UPTIME_STATUSES),
2153
+ last_verdict: z14.enum(SLOT_VERDICTS).nullable(),
1567
2154
  last_slot_at: iso2.nullable(),
1568
2155
  incident_id: uuid3.nullable(),
1569
- down_streak: z10.number().int().nonnegative(),
1570
- up_streak: z10.number().int().nonnegative(),
1571
- regions: z10.array(uptimeRegionStateSchema).max(3),
1572
- unobserved_regions: z10.array(z10.enum(UPTIME_REGIONS)).max(3),
2156
+ down_streak: z14.number().int().nonnegative(),
2157
+ up_streak: z14.number().int().nonnegative(),
2158
+ regions: z14.array(uptimeRegionStateSchema).max(3),
2159
+ unobserved_regions: z14.array(z14.enum(UPTIME_REGIONS)).max(3),
1573
2160
  cert_not_after: iso2.nullable(),
1574
- cert_expiring: z10.boolean(),
1575
- run_now: z10.object({ run_id: z10.string().max(64), results: z10.array(uptimeRegionStateSchema).max(3) }).nullable()
2161
+ cert_expiring: z14.boolean(),
2162
+ run_now: z14.object({ run_id: z14.string().max(64), results: z14.array(uptimeRegionStateSchema).max(3) }).nullable()
1576
2163
  });
1577
2164
  var UPTIME_EVENT_KINDS = ["opened", "resolved", "cert_expiring"];
1578
- var uptimeEventSchema = z10.object({
1579
- event_id: z10.string().regex(/^[A-Za-z0-9:_-]{8,96}$/),
2165
+ var uptimeEventSchema = z14.object({
2166
+ event_id: z14.string().regex(/^[A-Za-z0-9:_-]{8,96}$/),
1580
2167
  check_id: uuid3,
1581
- kind: z10.enum(UPTIME_EVENT_KINDS),
2168
+ kind: z14.enum(UPTIME_EVENT_KINDS),
1582
2169
  incident_id: uuid3.nullable(),
1583
2170
  at: iso2,
1584
- reason: z10.enum(UPTIME_REASONS).nullable(),
1585
- regions: z10.array(z10.enum(UPTIME_REGIONS)).max(3),
1586
- cert_days_left: z10.number().int().nullable()
2171
+ reason: z14.enum(UPTIME_REASONS).nullable(),
2172
+ regions: z14.array(z14.enum(UPTIME_REGIONS)).max(3),
2173
+ cert_days_left: z14.number().int().nullable()
1587
2174
  });
1588
- var uptimeMinuteSchema = z10.object({
2175
+ var uptimeMinuteSchema = z14.object({
1589
2176
  check_id: uuid3,
1590
2177
  minute: iso2,
1591
- up: z10.number().int().nonnegative(),
1592
- degraded: z10.number().int().nonnegative(),
1593
- down: z10.number().int().nonnegative(),
1594
- unknown: z10.number().int().nonnegative(),
1595
- latency: z10.array(z10.object({ region: z10.enum(UPTIME_REGIONS), n: z10.number().int().positive(), p50_ms: z10.number().nonnegative(), p95_ms: z10.number().nonnegative() })).max(3)
1596
- });
1597
- var uptimeReportSchema = z10.object({
1598
- v: z10.literal(1),
2178
+ up: z14.number().int().nonnegative(),
2179
+ degraded: z14.number().int().nonnegative(),
2180
+ down: z14.number().int().nonnegative(),
2181
+ unknown: z14.number().int().nonnegative(),
2182
+ latency: z14.array(z14.object({ region: z14.enum(UPTIME_REGIONS), n: z14.number().int().positive(), p50_ms: z14.number().nonnegative(), p95_ms: z14.number().nonnegative() })).max(3)
2183
+ });
2184
+ var uptimeReportSchema = z14.object({
2185
+ v: z14.literal(1),
1599
2186
  workspace_id: uuid3,
1600
- revision: z10.number().int().nonnegative(),
2187
+ revision: z14.number().int().nonnegative(),
1601
2188
  sent_at: iso2,
1602
- events: z10.array(uptimeEventSchema).max(UPTIME_LIMITS.reportMaxEvents),
1603
- statuses: z10.array(uptimeStatusReportSchema).max(UPTIME_LIMITS.reportMaxStatuses),
1604
- minutes: z10.array(uptimeMinuteSchema).max(UPTIME_LIMITS.reportMaxMinutes)
2189
+ events: z14.array(uptimeEventSchema).max(UPTIME_LIMITS.reportMaxEvents),
2190
+ statuses: z14.array(uptimeStatusReportSchema).max(UPTIME_LIMITS.reportMaxStatuses),
2191
+ minutes: z14.array(uptimeMinuteSchema).max(UPTIME_LIMITS.reportMaxMinutes)
1605
2192
  });
1606
- var probeFleetReportSchema = z10.object({
1607
- v: z10.literal(1),
2193
+ var probeFleetReportSchema = z14.object({
2194
+ v: z14.literal(1),
1608
2195
  sent_at: iso2,
1609
- probes: z10.array(z10.object({
2196
+ probes: z14.array(z14.object({
1610
2197
  probe_id: probeIdSchema,
1611
- region: z10.enum(UPTIME_REGIONS),
1612
- version: z10.string().max(40).nullable(),
2198
+ region: z14.enum(UPTIME_REGIONS),
2199
+ version: z14.string().max(40).nullable(),
1613
2200
  last_seen_at: iso2.nullable(),
1614
- lag_p99_ms: z10.number().nonnegative().nullable(),
1615
- checks_per_min: z10.number().nonnegative().nullable()
2201
+ lag_p99_ms: z14.number().nonnegative().nullable(),
2202
+ checks_per_min: z14.number().nonnegative().nullable()
1616
2203
  })).max(30),
1617
- regions_alive: z10.array(z10.enum(UPTIME_REGIONS)).max(3)
2204
+ regions_alive: z14.array(z14.enum(UPTIME_REGIONS)).max(3)
1618
2205
  });
1619
- var probeEnrollSchema = z10.object({
1620
- v: z10.literal(1),
2206
+ var probeEnrollSchema = z14.object({
2207
+ v: z14.literal(1),
1621
2208
  probe_id: probeIdSchema,
1622
- public_key: z10.string().regex(/^[A-Za-z0-9_-]{43}$/),
1623
- code: z10.string().regex(/^[A-Za-z0-9_-]{43}$/),
1624
- ts: z10.number().int().positive(),
1625
- sig: z10.string().regex(/^[A-Za-z0-9_-]{86}$/)
1626
- });
1627
- var uptimeEvidenceEnvelopeSchema = z10.object({
1628
- v: z10.literal(1),
1629
- check_id: z10.guid(),
1630
- slot: z10.number().int().nonnegative(),
1631
- region: z10.enum(UPTIME_REGIONS),
2209
+ public_key: z14.string().regex(/^[A-Za-z0-9_-]{43}$/),
2210
+ code: z14.string().regex(/^[A-Za-z0-9_-]{43}$/),
2211
+ ts: z14.number().int().positive(),
2212
+ sig: z14.string().regex(/^[A-Za-z0-9_-]{86}$/)
2213
+ });
2214
+ var uptimeEvidenceEnvelopeSchema = z14.object({
2215
+ v: z14.literal(1),
2216
+ check_id: z14.guid(),
2217
+ slot: z14.number().int().nonnegative(),
2218
+ region: z14.enum(UPTIME_REGIONS),
1632
2219
  probe_id: probeIdSchema,
1633
- at: z10.number().int().positive(),
1634
- sealed: z10.string().regex(/^[A-Za-z0-9_-]+$/).max(16384)
2220
+ at: z14.number().int().positive(),
2221
+ sealed: z14.string().regex(/^[A-Za-z0-9_-]+$/).max(16384)
1635
2222
  }).strict();
1636
- var uptimeEvidenceSchema = z10.object({
1637
- v: z10.literal(1),
1638
- check_id: z10.guid(),
1639
- slot: z10.number().int().nonnegative(),
1640
- region: z10.enum(UPTIME_REGIONS),
1641
- at: z10.number().int().positive(),
1642
- reason: z10.enum(UPTIME_REASONS).nullable(),
1643
- status_line: z10.string().max(200).nullable(),
1644
- headers: z10.record(z10.string().max(64), z10.string().max(512)).refine((h) => Object.keys(h).length <= 20),
1645
- body: z10.string().max(UPTIME_LIMITS.evidenceMaxBytes * 4).nullable(),
1646
- body_truncated: z10.boolean(),
2223
+ var uptimeEvidenceSchema = z14.object({
2224
+ v: z14.literal(1),
2225
+ check_id: z14.guid(),
2226
+ slot: z14.number().int().nonnegative(),
2227
+ region: z14.enum(UPTIME_REGIONS),
2228
+ at: z14.number().int().positive(),
2229
+ reason: z14.enum(UPTIME_REASONS).nullable(),
2230
+ status_line: z14.string().max(200).nullable(),
2231
+ headers: z14.record(z14.string().max(64), z14.string().max(512)).refine((h) => Object.keys(h).length <= 20),
2232
+ body: z14.string().max(UPTIME_LIMITS.evidenceMaxBytes * 4).nullable(),
2233
+ body_truncated: z14.boolean(),
1647
2234
  timings: timingsSchema.nullable(),
1648
- ip: z10.string().max(64).nullable(),
1649
- error: z10.string().max(300).nullable()
2235
+ ip: z14.string().max(64).nullable(),
2236
+ error: z14.string().max(300).nullable()
1650
2237
  }).strict();
1651
- var uptimeEvidenceListSchema = z10.object({
1652
- items: z10.array(uptimeEvidenceSchema.extend({ received_at: z10.number().int().positive() })).max(UPTIME_LIMITS.evidenceKeepPerCheck)
2238
+ var uptimeEvidenceListSchema = z14.object({
2239
+ items: z14.array(uptimeEvidenceSchema.extend({ received_at: z14.number().int().positive() })).max(UPTIME_LIMITS.evidenceKeepPerCheck)
1653
2240
  });
1654
2241
 
1655
2242
  // ../src/shared/contracts/api-ops/monitors.ts
2243
+ var anyMonitorInputSchema = z15.union([monitorInputSchema, signalMonitorInputSchema]);
2244
+ var MAINTENANCE_INPUTS = {
2245
+ create: z15.object({ workspaceId: uuid, input: maintenanceInputSchema }),
2246
+ update: z15.object({ workspaceId: uuid, windowId: uuid, input: maintenanceInputSchema }),
2247
+ delete: z15.object({ workspaceId: uuid, windowId: uuid })
2248
+ };
1656
2249
  var MONITOR_INPUTS = {
1657
- create: z11.object({ projectId, slug: z11.string().regex(SLUG_RE), input: monitorInputSchema }),
1658
- update: z11.object({ monitorId: uuid, input: monitorInputSchema }),
1659
- delete: z11.object({ monitorId: uuid, confirmSlug: z11.string().max(64) }),
1660
- setPause: z11.object({ monitorId: uuid, until: holdUntil }),
1661
- setMuted: z11.object({ monitorId: uuid, muted: z11.boolean() }),
1662
- dismissDiscovery: z11.object({ discoveryId: uuid }),
1663
- rotatePing: z11.object({
2250
+ create: z15.object({ projectId, slug: z15.string().regex(SLUG_RE), input: anyMonitorInputSchema }),
2251
+ update: z15.object({ monitorId: uuid, input: anyMonitorInputSchema }),
2252
+ delete: z15.object({ monitorId: uuid, confirmSlug: z15.string().max(64) }),
2253
+ setPause: z15.object({ monitorId: uuid, until: holdUntil }),
2254
+ setMuted: z15.object({ monitorId: uuid, muted: z15.boolean() }),
2255
+ dismissDiscovery: z15.object({ discoveryId: uuid }),
2256
+ rotatePing: z15.object({
1664
2257
  monitorId: uuid,
1665
- graceHours: z11.number().int().refine((h) => HEARTBEAT_LIMITS.rotationGraceHoursChoices.includes(h))
2258
+ graceHours: z15.number().int().refine((h) => HEARTBEAT_LIMITS.rotationGraceHoursChoices.includes(h))
1666
2259
  }),
1667
- monitorOnly: z11.object({ monitorId: uuid })
2260
+ monitorOnly: z15.object({ monitorId: uuid })
1668
2261
  };
1669
2262
  var UPTIME_INPUTS = {
1670
2263
  create: uptimeCheckInputSchema,
1671
- update: z11.object({ checkId: uuid, input: uptimeCheckInputSchema }),
1672
- checkOnly: z11.object({ checkId: uuid }),
1673
- setHold: z11.object({ checkId: uuid, kind: z11.enum(["pause", "mute"]), until: holdUntil })
2264
+ update: z15.object({ checkId: uuid, input: uptimeCheckInputSchema }),
2265
+ checkOnly: z15.object({ checkId: uuid }),
2266
+ setHold: z15.object({ checkId: uuid, kind: z15.enum(["pause", "mute"]), until: holdUntil })
1674
2267
  };
1675
2268
  var SLO_INPUTS = {
1676
- create: z11.object({ workspaceId: uuid, input: sloInputSchema }),
1677
- update: z11.object({ sloId: uuid, input: sloInputSchema }),
1678
- sloOnly: z11.object({ sloId: uuid }),
1679
- setHold: z11.object({ sloId: uuid, kind: z11.enum(["pause", "mute"]), until: holdUntil }),
1680
- import: z11.object({
2269
+ create: z15.object({ workspaceId: uuid, input: sloInputSchema }),
2270
+ update: z15.object({ sloId: uuid, input: sloInputSchema }),
2271
+ sloOnly: z15.object({ sloId: uuid }),
2272
+ setHold: z15.object({ sloId: uuid, kind: z15.enum(["pause", "mute"]), until: holdUntil }),
2273
+ import: z15.object({
1681
2274
  workspaceId: uuid,
1682
- text: z11.string().max(SLO_LIMITS.openSloMaxBytes * 2),
1683
- dryRun: z11.boolean()
2275
+ text: z15.string().max(SLO_LIMITS.openSloMaxBytes * 2),
2276
+ dryRun: z15.boolean()
1684
2277
  })
1685
2278
  };
1686
2279
  var m = "monitors:write";
@@ -1692,13 +2285,13 @@ var MONITOR_OPERATIONS = [
1692
2285
  scope: m,
1693
2286
  sensitivity: "normal",
1694
2287
  kind: "write",
1695
- rpcs: ["create_monitor", "create_heartbeat_monitor"],
2288
+ rpcs: ["create_monitor", "create_heartbeat_monitor", "create_signal_monitor"],
1696
2289
  input: MONITOR_INPUTS.create,
1697
2290
  bodyField: "input",
1698
2291
  idempotency: "required",
1699
2292
  status: 201,
1700
2293
  mcp: "configure",
1701
- summary: "Create a cron or heartbeat monitor. A heartbeat monitor returns its ping token once.",
2294
+ summary: "Create a cron or heartbeat monitor, or a signal monitor (`settings.type`: count, assertion, deadline, progress). A heartbeat monitor returns its ping token once.",
1702
2295
  secretOutput: ["ping_token"],
1703
2296
  ui: ["monitors#createMonitor"]
1704
2297
  }),
@@ -1709,13 +2302,13 @@ var MONITOR_OPERATIONS = [
1709
2302
  scope: m,
1710
2303
  sensitivity: "normal",
1711
2304
  kind: "write",
1712
- rpcs: ["update_monitor"],
2305
+ rpcs: ["update_monitor", "update_signal_monitor"],
1713
2306
  input: MONITOR_INPUTS.update,
1714
2307
  bodyField: "input",
1715
2308
  ifMatch: true,
1716
2309
  idempotency: "none",
1717
2310
  mcp: "configure",
1718
- summary: "Replace a monitor's schedule, margins and thresholds.",
2311
+ summary: "Replace a monitor's schedule, margins and thresholds, or a signal monitor's settings (the type stays).",
1719
2312
  ui: ["monitors#updateMonitor"]
1720
2313
  }),
1721
2314
  op({
@@ -1970,23 +2563,71 @@ var MONITOR_OPERATIONS = [
1970
2563
  mcp: "configure",
1971
2564
  summary: "Import OpenSLO YAML, all or nothing; `dry_run` returns the plan without applying it.",
1972
2565
  ui: ["slos#importOpenSlo"]
2566
+ }),
2567
+ op({
2568
+ id: "maintenance.create",
2569
+ method: "POST",
2570
+ path: "/v1/maintenance-windows",
2571
+ scope: m,
2572
+ sensitivity: "normal",
2573
+ kind: "write",
2574
+ rpcs: ["create_maintenance_window"],
2575
+ input: MAINTENANCE_INPUTS.create,
2576
+ bodyField: "input",
2577
+ workspace: true,
2578
+ idempotency: "required",
2579
+ status: 201,
2580
+ mcp: "configure",
2581
+ summary: "Hold back monitor notifications during a one-off or weekly window (workspace, projects or monitors); monitors keep evaluating and recording.",
2582
+ ui: ["maintenance#createMaintenanceWindow"]
2583
+ }),
2584
+ op({
2585
+ id: "maintenance.update",
2586
+ method: "PATCH",
2587
+ path: "/v1/maintenance-windows/{window_id}",
2588
+ scope: m,
2589
+ sensitivity: "normal",
2590
+ kind: "write",
2591
+ rpcs: ["update_maintenance_window"],
2592
+ input: MAINTENANCE_INPUTS.update,
2593
+ bodyField: "input",
2594
+ workspace: true,
2595
+ idempotency: "none",
2596
+ mcp: "configure",
2597
+ summary: "Replace a maintenance window's scope, times and reason.",
2598
+ ui: ["maintenance#updateMaintenanceWindow"]
2599
+ }),
2600
+ op({
2601
+ id: "maintenance.delete",
2602
+ method: "DELETE",
2603
+ path: "/v1/maintenance-windows/{window_id}",
2604
+ scope: m,
2605
+ sensitivity: "normal",
2606
+ kind: "write",
2607
+ rpcs: ["delete_maintenance_window"],
2608
+ input: MAINTENANCE_INPUTS.delete,
2609
+ workspace: true,
2610
+ idempotency: "none",
2611
+ mcp: "configure",
2612
+ summary: "Delete a maintenance window; notifications resume at once.",
2613
+ ui: ["maintenance#deleteMaintenanceWindow"]
1973
2614
  })
1974
2615
  ];
1975
2616
 
1976
2617
  // ../src/shared/contracts/api-ops/node-data.ts
1977
- import { z as z12 } from "zod";
1978
- var issueId = z12.number().int().positive();
1979
- var csv = z12.string().min(1).max(2000);
1980
- var name2 = z12.string().min(1).max(256);
1981
- var period = z12.enum(["1h", "24h", "7d", "14d", "30d"]);
1982
- var nodeCursor = z12.string().min(1).max(600).optional();
2618
+ import { z as z16 } from "zod";
2619
+ var issueId = z16.number().int().positive();
2620
+ var csv = z16.string().min(1).max(2000);
2621
+ var name2 = z16.string().min(1).max(256);
2622
+ var period = z16.enum(["1h", "24h", "7d", "14d", "30d"]);
2623
+ var nodeCursor = z16.string().min(1).max(600).optional();
1983
2624
  var windowFields = {
1984
- start: z12.string().max(40).optional(),
1985
- end: z12.string().max(40).optional()
2625
+ start: z16.string().max(40).optional(),
2626
+ end: z16.string().max(40).optional()
1986
2627
  };
1987
- var traceId = z12.string().regex(/^[0-9a-fA-F]{32}$/);
1988
- var spanId = z12.string().regex(/^[0-9a-fA-F]{16}$/);
1989
- var attrs = z12.string().max(2000).optional();
2628
+ var traceId = z16.string().regex(/^[0-9a-fA-F]{32}$/);
2629
+ var spanId = z16.string().regex(/^[0-9a-fA-F]{16}$/);
2630
+ var attrs = z16.string().max(2000).optional();
1990
2631
  var telemetryCommon = {
1991
2632
  ...windowFields,
1992
2633
  project: csv.optional(),
@@ -1994,91 +2635,112 @@ var telemetryCommon = {
1994
2635
  service: csv.optional(),
1995
2636
  attrs
1996
2637
  };
1997
- var issueChange = z12.union([
1998
- z12.object({ action: z12.literal("resolve"), inNextRelease: z12.boolean().optional() }),
1999
- z12.object({ action: z12.literal("unresolve") }),
2000
- z12.object({ action: z12.literal("archive"), mode: z12.enum(["until_escalating", "forever"]) }),
2001
- z12.object({
2002
- action: z12.literal("archive"),
2003
- mode: z12.literal("until_condition"),
2004
- events: z12.number().int().min(1).max(1e6).optional(),
2005
- users: z12.number().int().min(1).max(1e5).optional(),
2006
- until: z12.string().datetime().optional()
2007
- }),
2008
- z12.object({ action: z12.literal("assign"), userId: z12.guid().nullable() }),
2009
- z12.object({ action: z12.literal("priority"), priority: z12.enum(["low", "medium", "high"]) })
2638
+ var issueChange = z16.union([
2639
+ z16.object({ action: z16.literal("resolve"), inNextRelease: z16.boolean().optional() }),
2640
+ z16.object({ action: z16.literal("unresolve") }),
2641
+ z16.object({ action: z16.literal("archive"), mode: z16.enum(["until_escalating", "forever"]) }),
2642
+ z16.object({
2643
+ action: z16.literal("archive"),
2644
+ mode: z16.literal("until_condition"),
2645
+ events: z16.number().int().min(1).max(1e6).optional(),
2646
+ users: z16.number().int().min(1).max(1e5).optional(),
2647
+ until: z16.string().datetime().optional()
2648
+ }),
2649
+ z16.object({ action: z16.literal("assign"), userId: z16.guid().nullable() }),
2650
+ z16.object({ action: z16.literal("priority"), priority: z16.enum(["low", "medium", "high"]) })
2010
2651
  ]);
2011
2652
  var NODE_INPUTS = {
2012
- issuesList: z12.object({
2653
+ issuesList: z16.object({
2013
2654
  project: csv.optional(),
2014
- status: z12.enum(["unresolved", "resolved", "archived", "all"]).optional(),
2655
+ status: z16.enum(["unresolved", "resolved", "archived", "all"]).optional(),
2015
2656
  level: csv.optional(),
2016
2657
  priority: csv.optional(),
2017
2658
  environment: csv.optional(),
2018
2659
  release: csv.optional(),
2019
- assignee: z12.string().max(64).optional(),
2660
+ assignee: z16.string().max(64).optional(),
2020
2661
  period: period.optional(),
2021
- q: z12.string().max(200).optional(),
2022
- sort: z12.enum(["last_seen", "first_seen", "events", "users", "priority"]).optional(),
2662
+ q: z16.string().max(200).optional(),
2663
+ sort: z16.enum(["last_seen", "first_seen", "events", "users", "priority"]).optional(),
2023
2664
  cursor: nodeCursor,
2024
- limit: z12.number().int().min(1).max(100).optional()
2665
+ limit: z16.number().int().min(1).max(100).optional()
2025
2666
  }),
2026
- issue: z12.object({ issueId }),
2027
- issueStats: z12.object({ issueId, range: z12.enum(["24h", "30d"]).optional() }),
2028
- issueEvents: z12.object({ issueId, cursor: nodeCursor }),
2029
- issueEvent: z12.object({
2667
+ issue: z16.object({ issueId }),
2668
+ issueStats: z16.object({ issueId, range: z16.enum(["24h", "30d"]).optional() }),
2669
+ issueEvents: z16.object({ issueId, cursor: nodeCursor }),
2670
+ issueEvent: z16.object({
2030
2671
  issueId,
2031
- eventId: z12.string().regex(/^([0-9a-f]{32}|latest|oldest)$/)
2672
+ eventId: z16.string().regex(/^([0-9a-f]{32}|latest|oldest)$/)
2032
2673
  }),
2033
- issueUpdate: z12.object({ issueId, change: issueChange }),
2034
- issuesBulk: z12.object({
2035
- issueIds: z12.array(issueId).min(1).max(100),
2674
+ issueUpdate: z16.object({ issueId, change: issueChange }),
2675
+ issuesBulk: z16.object({
2676
+ issueIds: z16.array(issueId).min(1).max(100),
2036
2677
  action: issueChange
2037
2678
  }),
2038
- spansList: z12.object({
2679
+ spansList: z16.object({
2039
2680
  ...telemetryCommon,
2040
- operation: z12.string().min(1).max(1024).optional(),
2041
- status: z12.enum(["unset", "ok", "error"]).optional(),
2042
- kind: z12.enum(["internal", "server", "client", "producer", "consumer"]).optional(),
2043
- minDurationMs: z12.number().min(0).max(86400000).optional(),
2044
- maxDurationMs: z12.number().min(0).max(86400000).optional(),
2045
- mode: z12.enum(["spans", "traces"]).optional(),
2681
+ operation: z16.string().min(1).max(1024).optional(),
2682
+ status: z16.enum(["unset", "ok", "error"]).optional(),
2683
+ kind: z16.enum(["internal", "server", "client", "producer", "consumer"]).optional(),
2684
+ minDurationMs: z16.number().min(0).max(86400000).optional(),
2685
+ maxDurationMs: z16.number().min(0).max(86400000).optional(),
2686
+ mode: z16.enum(["spans", "traces"]).optional(),
2046
2687
  cursor: nodeCursor
2047
2688
  }),
2048
- spansHistogram: z12.object({
2689
+ spansHistogram: z16.object({
2049
2690
  ...telemetryCommon,
2050
- operation: z12.string().min(1).max(1024).optional(),
2051
- status: z12.enum(["unset", "ok", "error"]).optional()
2691
+ operation: z16.string().min(1).max(1024).optional(),
2692
+ status: z16.enum(["unset", "ok", "error"]).optional()
2052
2693
  }),
2053
- trace: z12.object({ traceId }),
2054
- traceSpans: z12.object({ traceId, errorsOnly: z12.enum(["1"]).optional(), ...windowFields }),
2055
- span: z12.object({ traceId, spanId, ...windowFields }),
2056
- logsList: z12.object({
2694
+ trace: z16.object({ traceId }),
2695
+ traceSpans: z16.object({ traceId, errorsOnly: z16.enum(["1"]).optional(), ...windowFields }),
2696
+ span: z16.object({ traceId, spanId, ...windowFields }),
2697
+ logsList: z16.object({
2057
2698
  ...telemetryCommon,
2058
- severityMin: z12.enum(["trace", "debug", "info", "warn", "error", "fatal"]).optional(),
2699
+ severityMin: z16.enum(["trace", "debug", "info", "warn", "error", "fatal"]).optional(),
2059
2700
  traceId: traceId.optional(),
2060
2701
  spanId: spanId.optional(),
2061
- q: z12.string().max(500).optional(),
2062
- order: z12.enum(["asc", "desc"]).optional(),
2702
+ q: z16.string().max(500).optional(),
2703
+ order: z16.enum(["asc", "desc"]).optional(),
2063
2704
  cursor: nodeCursor
2064
2705
  }),
2065
- logsFacets: z12.object({
2706
+ logsFacets: z16.object({
2066
2707
  ...telemetryCommon,
2067
- severityMin: z12.enum(["trace", "debug", "info", "warn", "error", "fatal"]).optional(),
2068
- q: z12.string().max(500).optional()
2708
+ severityMin: z16.enum(["trace", "debug", "info", "warn", "error", "fatal"]).optional(),
2709
+ q: z16.string().max(500).optional()
2069
2710
  }),
2070
- logAround: z12.object({
2711
+ logAround: z16.object({
2071
2712
  logId: name2,
2072
- at: z12.string().max(40),
2073
- same: z12.enum(["service", "trace"]).optional(),
2074
- before: z12.number().int().min(0).max(200).optional(),
2075
- after: z12.number().int().min(0).max(200).optional()
2076
- }),
2077
- telemetryUsage: z12.object({ project: csv.optional(), days: z12.number().int().min(1).max(31).optional() }),
2078
- ticket: z12.object({
2079
- scope: z12.enum(["read", "write"]).default("read"),
2080
- project: z12.number().int().positive().optional(),
2081
- environment: z12.string().min(1).max(64).optional()
2713
+ at: z16.string().max(40),
2714
+ same: z16.enum(["service", "trace"]).optional(),
2715
+ before: z16.number().int().min(0).max(200).optional(),
2716
+ after: z16.number().int().min(0).max(200).optional()
2717
+ }),
2718
+ telemetryUsage: z16.object({ project: csv.optional(), days: z16.number().int().min(1).max(31).optional() }),
2719
+ monitorSignal: z16.object({ monitorId: z16.guid(), hours: z16.number().int().min(1).max(24).optional() }),
2720
+ monitorOccurrences: z16.object({
2721
+ monitorId: z16.guid(),
2722
+ state: z16.enum(["open", "finished", "all"]).optional(),
2723
+ environment: z16.string().min(1).max(64).optional(),
2724
+ cursor: nodeCursor
2725
+ }),
2726
+ monitorBacktest: z16.object({ project: z16.number().int().positive(), settings: backtestSettingsSchema }),
2727
+ occurrenceCreate: z16.object({
2728
+ project: z16.number().int().positive(),
2729
+ monitorSlug: occurrenceInputSchema.shape.monitor_slug,
2730
+ occurrenceId: occurrenceInputSchema.shape.occurrence_id,
2731
+ dueAt: occurrenceInputSchema.shape.due_at,
2732
+ environment: occurrenceInputSchema.shape.environment
2733
+ }),
2734
+ occurrenceCancel: z16.object({
2735
+ project: z16.number().int().positive(),
2736
+ monitorSlug: z16.string().regex(SLUG_RE),
2737
+ occurrenceId: z16.string().regex(OCCURRENCE_ID_RE),
2738
+ environment: z16.string().min(1).max(64).optional()
2739
+ }),
2740
+ ticket: z16.object({
2741
+ scope: z16.enum(["read", "write"]).default("read"),
2742
+ project: z16.number().int().positive().optional(),
2743
+ environment: z16.string().min(1).max(64).optional()
2082
2744
  })
2083
2745
  };
2084
2746
  var N = NODE_INPUTS;
@@ -2249,6 +2911,60 @@ var NODE_OPERATIONS = [
2249
2911
  node: { path: "q/telemetry/usage" },
2250
2912
  summary: "Stored spans and logs per day and project on the node."
2251
2913
  }),
2914
+ op({
2915
+ ...read,
2916
+ id: "monitors.signal",
2917
+ path: "/v1/monitors/{monitor_id}/signal",
2918
+ scope: "monitors:read",
2919
+ input: N.monitorSignal,
2920
+ node: { path: "q/monitors/{monitor_id}/signal" },
2921
+ mcp: "reliability",
2922
+ summary: "A signal monitor's minute counts (count/assertion) for up to 24 h per environment, and its open runs (progress, deadline)."
2923
+ }),
2924
+ op({
2925
+ ...read,
2926
+ id: "monitors.occurrences",
2927
+ path: "/v1/monitors/{monitor_id}/occurrences",
2928
+ scope: "monitors:read",
2929
+ input: N.monitorOccurrences,
2930
+ node: { path: "q/monitors/{monitor_id}/occurrences", list: "occurrences" },
2931
+ paged: true,
2932
+ mcp: "reliability",
2933
+ summary: "Occurrences of a deadline monitor (pending, on time, late, missed, failed, cancelled), newest due first."
2934
+ }),
2935
+ op({
2936
+ ...read,
2937
+ id: "monitors.backtest",
2938
+ method: "POST",
2939
+ path: "/v1/monitors/backtest",
2940
+ scope: "monitors:read",
2941
+ input: N.monitorBacktest,
2942
+ node: { path: "q/monitors/backtest" },
2943
+ mcp: "reliability",
2944
+ summary: "How often count/assertion settings would have alerted over the last 30 days of stored data (same rule as the live evaluator)."
2945
+ }),
2946
+ op({
2947
+ ...read,
2948
+ id: "occurrences.create",
2949
+ method: "POST",
2950
+ path: "/v1/occurrences",
2951
+ scope: "monitors:write",
2952
+ input: N.occurrenceCreate,
2953
+ node: { path: "w/monitors/occurrences", body: "*" },
2954
+ mcp: "configure",
2955
+ summary: "Register one run a deadline monitor expects (`due_at` within 35 days); the same id again moves its due time while it is pending."
2956
+ }),
2957
+ op({
2958
+ ...read,
2959
+ id: "occurrences.cancel",
2960
+ method: "DELETE",
2961
+ path: "/v1/occurrences/{monitor_slug}/{occurrence_id}",
2962
+ scope: "monitors:write",
2963
+ input: N.occurrenceCancel,
2964
+ node: { path: "w/monitors/occurrences/cancel", body: "*" },
2965
+ mcp: "configure",
2966
+ summary: "Cancel a pending occurrence (the app moved or dropped the job); a cancelled occurrence never alerts."
2967
+ }),
2252
2968
  op({
2253
2969
  ...read,
2254
2970
  id: "issues.update",
@@ -2286,10 +3002,10 @@ var NODE_OPERATIONS = [
2286
3002
  ];
2287
3003
 
2288
3004
  // ../src/shared/contracts/api-ops/projects.ts
2289
- import { z as z17 } from "zod";
3005
+ import { z as z21 } from "zod";
2290
3006
 
2291
3007
  // ../src/shared/contracts/ingest-keys.ts
2292
- import { z as z13 } from "zod";
3008
+ import { z as z17 } from "zod";
2293
3009
  var INGEST_KEY_SCOPES = ["traces", "logs", "errors", "monitors"];
2294
3010
  var INGEST_KEY_STATES = ["active", "revoked"];
2295
3011
  var INGEST_KEY_LIMITS = {
@@ -2299,51 +3015,51 @@ var INGEST_KEY_LIMITS = {
2299
3015
  edgeCacheSeconds: 60
2300
3016
  };
2301
3017
  var CHECKIN_AUTH_MODES = ["public_or_key", "key_only"];
2302
- var ingestKeyConfigSchema = z13.object({
2303
- v: z13.literal(1),
2304
- key_id: z13.guid(),
2305
- project_public_id: z13.number().int().positive(),
2306
- project_id: z13.number().int().positive(),
2307
- workspace_id: z13.guid(),
3018
+ var ingestKeyConfigSchema = z17.object({
3019
+ v: z17.literal(1),
3020
+ key_id: z17.guid(),
3021
+ project_public_id: z17.number().int().positive(),
3022
+ project_id: z17.number().int().positive(),
3023
+ workspace_id: z17.guid(),
2308
3024
  node_id: nodeIdSchema,
2309
- scopes: z13.array(z13.enum(INGEST_KEY_SCOPES)).min(1).max(INGEST_KEY_SCOPES.length),
2310
- environments: z13.array(z13.string().max(INGEST_KEY_LIMITS.environmentMaxChars)).max(INGEST_KEY_LIMITS.environmentsMax),
2311
- expires_at: z13.string().datetime({ offset: true }).nullable(),
2312
- state: z13.enum(INGEST_KEY_STATES),
2313
- workspace_status: z13.enum(["active", "suspended", "deleting"]),
2314
- ingest_kill: z13.boolean(),
2315
- telemetry_kill: z13.boolean(),
2316
- telemetry_rate_bytes_per_sec: z13.number().int().positive(),
2317
- telemetry_burst_bytes: z13.number().int().positive(),
2318
- traces_monthly_bytes: z13.number().int().positive(),
2319
- logs_monthly_bytes: z13.number().int().positive(),
2320
- telemetry_buffer_minutes: z13.number().int().min(1).max(1440),
2321
- revision: z13.number().int().nonnegative()
2322
- });
2323
- var createIngestKeyInputSchema = z13.object({
2324
- projectId: z13.number().int().positive(),
2325
- name: z13.string().trim().min(1).max(INGEST_KEY_LIMITS.nameMaxChars).refine((s) => !/[\u0000-\u001f\u007f]/.test(s)),
2326
- scopes: z13.array(z13.enum(INGEST_KEY_SCOPES)).min(1).max(INGEST_KEY_SCOPES.length),
2327
- environments: z13.array(z13.string().trim().min(1).max(INGEST_KEY_LIMITS.environmentMaxChars).regex(/^[^\s/\u0000-\u001f]+$/)).max(INGEST_KEY_LIMITS.environmentsMax),
2328
- expiresAt: z13.string().datetime({ offset: true }).nullable()
2329
- });
2330
- var ingestKeyRowSchema = z13.object({
2331
- id: z13.guid(),
2332
- project_id: z13.number().int().positive(),
2333
- name: z13.string(),
2334
- prefix: z13.string(),
2335
- scopes: z13.array(z13.enum(INGEST_KEY_SCOPES)),
2336
- environments: z13.array(z13.string()),
2337
- expires_at: z13.string().nullable(),
2338
- state: z13.enum(INGEST_KEY_STATES),
2339
- created_by: z13.guid().nullable(),
2340
- created_at: z13.string(),
2341
- revoked_at: z13.string().nullable(),
2342
- last_used_at: z13.string().nullable()
3025
+ scopes: z17.array(z17.enum(INGEST_KEY_SCOPES)).min(1).max(INGEST_KEY_SCOPES.length),
3026
+ environments: z17.array(z17.string().max(INGEST_KEY_LIMITS.environmentMaxChars)).max(INGEST_KEY_LIMITS.environmentsMax),
3027
+ expires_at: z17.string().datetime({ offset: true }).nullable(),
3028
+ state: z17.enum(INGEST_KEY_STATES),
3029
+ workspace_status: z17.enum(["active", "suspended", "deleting"]),
3030
+ ingest_kill: z17.boolean(),
3031
+ telemetry_kill: z17.boolean(),
3032
+ telemetry_rate_bytes_per_sec: z17.number().int().positive(),
3033
+ telemetry_burst_bytes: z17.number().int().positive(),
3034
+ traces_monthly_bytes: z17.number().int().positive(),
3035
+ logs_monthly_bytes: z17.number().int().positive(),
3036
+ telemetry_buffer_minutes: z17.number().int().min(1).max(1440),
3037
+ revision: z17.number().int().nonnegative()
3038
+ });
3039
+ var createIngestKeyInputSchema = z17.object({
3040
+ projectId: z17.number().int().positive(),
3041
+ name: z17.string().trim().min(1).max(INGEST_KEY_LIMITS.nameMaxChars).refine((s) => !/[\u0000-\u001f\u007f]/.test(s)),
3042
+ scopes: z17.array(z17.enum(INGEST_KEY_SCOPES)).min(1).max(INGEST_KEY_SCOPES.length),
3043
+ environments: z17.array(z17.string().trim().min(1).max(INGEST_KEY_LIMITS.environmentMaxChars).regex(/^[^\s/\u0000-\u001f]+$/)).max(INGEST_KEY_LIMITS.environmentsMax),
3044
+ expiresAt: z17.string().datetime({ offset: true }).nullable()
3045
+ });
3046
+ var ingestKeyRowSchema = z17.object({
3047
+ id: z17.guid(),
3048
+ project_id: z17.number().int().positive(),
3049
+ name: z17.string(),
3050
+ prefix: z17.string(),
3051
+ scopes: z17.array(z17.enum(INGEST_KEY_SCOPES)),
3052
+ environments: z17.array(z17.string()),
3053
+ expires_at: z17.string().nullable(),
3054
+ state: z17.enum(INGEST_KEY_STATES),
3055
+ created_by: z17.guid().nullable(),
3056
+ created_at: z17.string(),
3057
+ revoked_at: z17.string().nullable(),
3058
+ last_used_at: z17.string().nullable()
2343
3059
  });
2344
3060
 
2345
3061
  // ../src/shared/contracts/integration-health.ts
2346
- import { z as z14 } from "zod";
3062
+ import { z as z18 } from "zod";
2347
3063
 
2348
3064
  // ../src/shared/contracts/platforms.ts
2349
3065
  var PLATFORMS = [
@@ -2357,116 +3073,116 @@ var PLATFORMS = [
2357
3073
 
2358
3074
  // ../src/shared/contracts/integration-health.ts
2359
3075
  var VERIFICATION_ID_RE = /^bv1_[0-9a-f]{32}$/;
2360
- var verificationIdSchema = z14.string().regex(VERIFICATION_ID_RE);
3076
+ var verificationIdSchema = z18.string().regex(VERIFICATION_ID_RE);
2361
3077
  var SURFACES = ["browser", "server"];
2362
3078
  var RECEIPT_SURFACES = ["browser", "server", "belvador"];
2363
3079
  var CHECKS = ["delivery", "uncaught", "pipeline"];
2364
3080
  var HOOK_STATES = ["ok", "missing", "unknown"];
2365
- var verificationContextSchema = z14.object({
2366
- v: z14.literal(1),
2367
- surface: z14.enum(RECEIPT_SURFACES),
2368
- check: z14.enum(CHECKS),
2369
- hook: z14.enum(HOOK_STATES).optional(),
2370
- uncaught_expected: z14.boolean().optional()
2371
- });
2372
- var iso3 = z14.string().datetime();
2373
- var projectId3 = z14.number().int().positive();
2374
- var verificationReceiptSchema = z14.object({
3081
+ var verificationContextSchema = z18.object({
3082
+ v: z18.literal(1),
3083
+ surface: z18.enum(RECEIPT_SURFACES),
3084
+ check: z18.enum(CHECKS),
3085
+ hook: z18.enum(HOOK_STATES).optional(),
3086
+ uncaught_expected: z18.boolean().optional()
3087
+ });
3088
+ var iso3 = z18.string().datetime();
3089
+ var projectId3 = z18.number().int().positive();
3090
+ var verificationReceiptSchema = z18.object({
2375
3091
  project_id: projectId3,
2376
3092
  verification_id: verificationIdSchema,
2377
- surface: z14.enum(RECEIPT_SURFACES),
2378
- check: z14.enum(CHECKS),
2379
- hook: z14.enum(HOOK_STATES),
2380
- uncaught_expected: z14.boolean(),
2381
- sdk_name: z14.string().max(80),
2382
- sdk_version: z14.string().max(40),
2383
- environment: z14.string().max(64),
2384
- release: z14.string().max(200),
2385
- source_host: z14.string().max(253),
3093
+ surface: z18.enum(RECEIPT_SURFACES),
3094
+ check: z18.enum(CHECKS),
3095
+ hook: z18.enum(HOOK_STATES),
3096
+ uncaught_expected: z18.boolean(),
3097
+ sdk_name: z18.string().max(80),
3098
+ sdk_version: z18.string().max(40),
3099
+ environment: z18.string().max(64),
3100
+ release: z18.string().max(200),
3101
+ source_host: z18.string().max(253),
2386
3102
  received_at: iso3
2387
3103
  });
2388
3104
  var SDK_DELIVERY_DROP_REASONS = ["network_error", "queue_overflow", "send_error"];
2389
- var clientDiscardSchema = z14.object({
3105
+ var clientDiscardSchema = z18.object({
2390
3106
  hour: iso3,
2391
- reason: z14.enum(SDK_DELIVERY_DROP_REASONS),
2392
- n: z14.number().int().nonnegative()
3107
+ reason: z18.enum(SDK_DELIVERY_DROP_REASONS),
3108
+ n: z18.number().int().nonnegative()
2393
3109
  });
2394
- var edgeVerificationRequestSchema = z14.object({
2395
- v: z14.literal(1),
3110
+ var edgeVerificationRequestSchema = z18.object({
3111
+ v: z18.literal(1),
2396
3112
  project_id: projectId3,
2397
3113
  verification_id: verificationIdSchema
2398
3114
  });
2399
- var readbackCheckSchema = z14.object({
2400
- surface: z14.enum(RECEIPT_SURFACES),
2401
- check: z14.enum(CHECKS),
2402
- hook: z14.enum(HOOK_STATES),
3115
+ var readbackCheckSchema = z18.object({
3116
+ surface: z18.enum(RECEIPT_SURFACES),
3117
+ check: z18.enum(CHECKS),
3118
+ hook: z18.enum(HOOK_STATES),
2403
3119
  received_at: iso3
2404
3120
  });
2405
- var edgeVerificationResponseSchema = z14.object({
2406
- checks: z14.array(readbackCheckSchema).max(8)
3121
+ var edgeVerificationResponseSchema = z18.object({
3122
+ checks: z18.array(readbackCheckSchema).max(8)
2407
3123
  });
2408
- var readbackResponseSchema = z14.object({
2409
- v: z14.literal(1),
3124
+ var readbackResponseSchema = z18.object({
3125
+ v: z18.literal(1),
2410
3126
  verification_id: verificationIdSchema,
2411
- node: z14.enum(["connected", "offline"]),
2412
- checks: z14.array(readbackCheckSchema).max(8)
3127
+ node: z18.enum(["connected", "offline"]),
3128
+ checks: z18.array(readbackCheckSchema).max(8)
2413
3129
  });
2414
3130
  var ENVIRONMENT_RE = /^[^\u0000-\u001f]{1,64}$/;
2415
- var projectRuntimeSchema = z14.object({
3131
+ var projectRuntimeSchema = z18.object({
2416
3132
  project_id: projectId3,
2417
- environment: z14.string().max(64),
2418
- surface: z14.enum(SURFACES),
2419
- sdk_name: z14.string().max(80),
2420
- sdk_version: z14.string().max(40),
2421
- latest_release: z14.string().max(200),
3133
+ environment: z18.string().max(64),
3134
+ surface: z18.enum(SURFACES),
3135
+ sdk_name: z18.string().max(80),
3136
+ sdk_version: z18.string().max(40),
3137
+ latest_release: z18.string().max(200),
2422
3138
  first_seen: iso3,
2423
3139
  last_seen: iso3,
2424
- events_24h: z14.number().int().nonnegative(),
2425
- check_ins_24h: z14.number().int().nonnegative()
3140
+ events_24h: z18.number().int().nonnegative(),
3141
+ check_ins_24h: z18.number().int().nonnegative()
2426
3142
  });
2427
3143
 
2428
3144
  // ../src/shared/contracts/node-config.ts
2429
- import { z as z16 } from "zod";
3145
+ import { z as z20 } from "zod";
2430
3146
 
2431
3147
  // ../src/shared/contracts/backup.ts
2432
- import { z as z15 } from "zod";
3148
+ import { z as z19 } from "zod";
2433
3149
  var BACKUP_KINDS = ["daily", "weekly", "manual", "pre_upgrade"];
2434
- var ageRecipient = z15.string().regex(/^age1[02-9ac-hj-np-z]{58}$/);
2435
- var backupIdSchema = z15.string().regex(/^[a-z0-9-]{8,64}$/);
2436
- var nodeBackupConfigSchema = z15.object({
2437
- enabled: z15.boolean(),
2438
- hour_utc: z15.number().int().min(0).max(23),
2439
- weekly_day: z15.number().int().min(1).max(7),
3150
+ var ageRecipient = z19.string().regex(/^age1[02-9ac-hj-np-z]{58}$/);
3151
+ var backupIdSchema = z19.string().regex(/^[a-z0-9-]{8,64}$/);
3152
+ var nodeBackupConfigSchema = z19.object({
3153
+ enabled: z19.boolean(),
3154
+ hour_utc: z19.number().int().min(0).max(23),
3155
+ weekly_day: z19.number().int().min(1).max(7),
2440
3156
  workspace_recipient: ageRecipient
2441
3157
  });
2442
- var backupCredentialsRequestSchema = z15.object({
2443
- mode: z15.enum(["upload", "download"]),
3158
+ var backupCredentialsRequestSchema = z19.object({
3159
+ mode: z19.enum(["upload", "download"]),
2444
3160
  backup_id: backupIdSchema,
2445
- source_node_id: z15.guid().optional()
2446
- });
2447
- var backupCredentialsSchema = z15.object({
2448
- endpoint: z15.string().url(),
2449
- bucket: z15.string().regex(/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/),
2450
- prefix: z15.string().regex(/^backups\/[0-9a-f-]{36}\/$/),
2451
- access_key_id: z15.string().min(8).max(200),
2452
- secret_access_key: z15.string().min(8).max(200),
2453
- session_token: z15.string().min(8).max(4000),
2454
- expires_at: z15.string().datetime()
2455
- });
2456
- var rowCountsSchema = z15.record(z15.string().regex(/^[a-z_][a-z0-9_]{0,63}$/), z15.number().int().nonnegative());
2457
- var backupManifestSchema = z15.object({
2458
- v: z15.literal(1),
3161
+ source_node_id: z19.guid().optional()
3162
+ });
3163
+ var backupCredentialsSchema = z19.object({
3164
+ endpoint: z19.string().url(),
3165
+ bucket: z19.string().regex(/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/),
3166
+ prefix: z19.string().regex(/^backups\/[0-9a-f-]{36}\/$/),
3167
+ access_key_id: z19.string().min(8).max(200),
3168
+ secret_access_key: z19.string().min(8).max(200),
3169
+ session_token: z19.string().min(8).max(4000),
3170
+ expires_at: z19.string().datetime()
3171
+ });
3172
+ var rowCountsSchema = z19.record(z19.string().regex(/^[a-z_][a-z0-9_]{0,63}$/), z19.number().int().nonnegative());
3173
+ var backupManifestSchema = z19.object({
3174
+ v: z19.literal(1),
2459
3175
  backup_id: backupIdSchema,
2460
- node_id: z15.guid(),
2461
- kind: z15.enum(BACKUP_KINDS),
2462
- created_at: z15.string().datetime(),
2463
- object_key: z15.string(),
2464
- size_bytes: z15.number().int().nonnegative(),
2465
- sha256: z15.string().regex(/^[0-9a-f]{64}$/),
2466
- clickhouse_version: z15.string().max(40),
2467
- schema_version: z15.number().int().nonnegative(),
3176
+ node_id: z19.guid(),
3177
+ kind: z19.enum(BACKUP_KINDS),
3178
+ created_at: z19.string().datetime(),
3179
+ object_key: z19.string(),
3180
+ size_bytes: z19.number().int().nonnegative(),
3181
+ sha256: z19.string().regex(/^[0-9a-f]{64}$/),
3182
+ clickhouse_version: z19.string().max(40),
3183
+ schema_version: z19.number().int().nonnegative(),
2468
3184
  row_counts: rowCountsSchema,
2469
- recipients: z15.array(z15.string().regex(/^[0-9a-f]{8}$/)).min(1).max(4)
3185
+ recipients: z19.array(z19.string().regex(/^[0-9a-f]{8}$/)).min(1).max(4)
2470
3186
  });
2471
3187
  var BACKUP_ERROR_CODES = [
2472
3188
  "CLICKHOUSE_BACKUP_FAILED",
@@ -2480,48 +3196,48 @@ var BACKUP_ERROR_CODES = [
2480
3196
  "RESTORE_FAILED",
2481
3197
  "ROW_COUNT_MISMATCH"
2482
3198
  ];
2483
- var backupReportSchema = z15.object({
3199
+ var backupReportSchema = z19.object({
2484
3200
  backup_id: backupIdSchema,
2485
- kind: z15.enum(BACKUP_KINDS),
2486
- status: z15.enum(["succeeded", "failed"]),
2487
- started_at: z15.string().datetime(),
2488
- finished_at: z15.string().datetime(),
3201
+ kind: z19.enum(BACKUP_KINDS),
3202
+ status: z19.enum(["succeeded", "failed"]),
3203
+ started_at: z19.string().datetime(),
3204
+ finished_at: z19.string().datetime(),
2489
3205
  manifest: backupManifestSchema.nullable(),
2490
- error_code: z15.enum(BACKUP_ERROR_CODES).nullable()
3206
+ error_code: z19.enum(BACKUP_ERROR_CODES).nullable()
2491
3207
  });
2492
- var drillReportSchema = z15.object({
3208
+ var drillReportSchema = z19.object({
2493
3209
  backup_id: backupIdSchema,
2494
- kind: z15.enum(["weekly_local", "monthly_new_machine"]),
2495
- status: z15.enum(["passed", "failed"]),
2496
- finished_at: z15.string().datetime(),
2497
- detail: z15.string().max(300),
2498
- error_code: z15.enum(BACKUP_ERROR_CODES).nullable()
2499
- });
2500
- var nodeIdentityEscrowSchema = z15.object({
2501
- v: z15.literal(1),
2502
- node_id: z15.guid(),
2503
- seal: z15.object({
2504
- publicKey: z15.string().regex(/^[A-Za-z0-9_-]{43}$/),
2505
- privateKey: z15.string().regex(/^[A-Za-z0-9_-]{43}$/)
2506
- }),
2507
- created_at: z15.string().datetime()
2508
- });
2509
- var restoreArgsSchema = z15.object({
2510
- job_id: z15.guid(),
2511
- workspace_id: z15.guid(),
2512
- source_node_id: z15.guid(),
3210
+ kind: z19.enum(["weekly_local", "monthly_new_machine"]),
3211
+ status: z19.enum(["passed", "failed"]),
3212
+ finished_at: z19.string().datetime(),
3213
+ detail: z19.string().max(300),
3214
+ error_code: z19.enum(BACKUP_ERROR_CODES).nullable()
3215
+ });
3216
+ var nodeIdentityEscrowSchema = z19.object({
3217
+ v: z19.literal(1),
3218
+ node_id: z19.guid(),
3219
+ seal: z19.object({
3220
+ publicKey: z19.string().regex(/^[A-Za-z0-9_-]{43}$/),
3221
+ privateKey: z19.string().regex(/^[A-Za-z0-9_-]{43}$/)
3222
+ }),
3223
+ created_at: z19.string().datetime()
3224
+ });
3225
+ var restoreArgsSchema = z19.object({
3226
+ job_id: z19.guid(),
3227
+ workspace_id: z19.guid(),
3228
+ source_node_id: z19.guid(),
2513
3229
  manifest: backupManifestSchema,
2514
- sealed_identity: z15.string().regex(/^[A-Za-z0-9_-]{40,2000}$/),
2515
- mode: z15.enum(["rebuild", "drill"])
3230
+ sealed_identity: z19.string().regex(/^[A-Za-z0-9_-]{40,2000}$/),
3231
+ mode: z19.enum(["rebuild", "drill"])
2516
3232
  });
2517
- var restoreReportSchema = z15.object({
2518
- job_id: z15.guid(),
3233
+ var restoreReportSchema = z19.object({
3234
+ job_id: z19.guid(),
2519
3235
  backup_id: backupIdSchema,
2520
- mode: z15.enum(["rebuild", "drill"]),
2521
- status: z15.enum(["succeeded", "failed"]),
2522
- finished_at: z15.string().datetime(),
2523
- detail: z15.string().max(300),
2524
- error_code: z15.enum(BACKUP_ERROR_CODES).nullable()
3236
+ mode: z19.enum(["rebuild", "drill"]),
3237
+ status: z19.enum(["succeeded", "failed"]),
3238
+ finished_at: z19.string().datetime(),
3239
+ detail: z19.string().max(300),
3240
+ error_code: z19.enum(BACKUP_ERROR_CODES).nullable()
2525
3241
  });
2526
3242
 
2527
3243
  // ../src/shared/contracts/node-config.ts
@@ -2535,79 +3251,81 @@ var SCRUB_GROUPS = [
2535
3251
  "headers"
2536
3252
  ];
2537
3253
  var MAX_NODE_MONITORS = 5000;
2538
- var kid = z16.string().regex(/^[A-Za-z0-9_-]{1,40}$/);
2539
- var publicKey = z16.string().regex(/^[A-Za-z0-9_-]{43}$/);
2540
- var nodeConfigSchema = z16.object({
2541
- v: z16.literal(1),
2542
- config_version: z16.number().int().positive(),
2543
- node_id: z16.guid(),
2544
- workspace_id: z16.guid(),
2545
- workspace_status: z16.enum(["active", "suspended"]),
2546
- issued_at: z16.string().datetime(),
2547
- retention_days: z16.number().int().min(1).max(3650),
2548
- channel: z16.enum(["stable", "canary"]).optional(),
2549
- projects: z16.array(z16.object({
2550
- project_id: z16.number().int().positive(),
2551
- slug: z16.string().max(64),
2552
- short_prefix: z16.string().regex(/^[A-Z0-9]{1,12}$/),
2553
- user_id_salt: z16.string().regex(/^[A-Za-z0-9_-]{22,64}$/),
2554
- scrub_disabled: z16.array(z16.enum(SCRUB_GROUPS)).max(SCRUB_GROUPS.length),
2555
- upload_tokens: z16.array(z16.object({
2556
- hash: z16.string().regex(/^[a-f0-9]{64}$/),
2557
- expires_at: z16.string().datetime()
3254
+ var kid = z20.string().regex(/^[A-Za-z0-9_-]{1,40}$/);
3255
+ var publicKey = z20.string().regex(/^[A-Za-z0-9_-]{43}$/);
3256
+ var nodeConfigSchema = z20.object({
3257
+ v: z20.literal(1),
3258
+ config_version: z20.number().int().positive(),
3259
+ node_id: z20.guid(),
3260
+ workspace_id: z20.guid(),
3261
+ workspace_status: z20.enum(["active", "suspended"]),
3262
+ issued_at: z20.string().datetime(),
3263
+ retention_days: z20.number().int().min(1).max(3650),
3264
+ channel: z20.enum(["stable", "canary"]).optional(),
3265
+ projects: z20.array(z20.object({
3266
+ project_id: z20.number().int().positive(),
3267
+ slug: z20.string().max(64),
3268
+ short_prefix: z20.string().regex(/^[A-Z0-9]{1,12}$/),
3269
+ user_id_salt: z20.string().regex(/^[A-Za-z0-9_-]{22,64}$/),
3270
+ scrub_disabled: z20.array(z20.enum(SCRUB_GROUPS)).max(SCRUB_GROUPS.length),
3271
+ upload_tokens: z20.array(z20.object({
3272
+ hash: z20.string().regex(/^[a-f0-9]{64}$/),
3273
+ expires_at: z20.string().datetime()
2558
3274
  })).max(10).optional()
2559
3275
  })).max(1000),
2560
- ticket_keys: z16.array(z16.object({ kid, public_key: publicKey, not_after: z16.string().datetime() })).min(1).max(5),
2561
- control_ops_keys: z16.array(z16.object({ kid, public_key: publicKey })).min(1).max(5),
2562
- kill_switches: z16.object({ ingest: z16.boolean(), alerts: z16.boolean() }),
3276
+ ticket_keys: z20.array(z20.object({ kid, public_key: publicKey, not_after: z20.string().datetime() })).min(1).max(5),
3277
+ control_ops_keys: z20.array(z20.object({ kid, public_key: publicKey })).min(1).max(5),
3278
+ kill_switches: z20.object({ ingest: z20.boolean(), alerts: z20.boolean() }),
2563
3279
  backup: nodeBackupConfigSchema.optional(),
2564
- purged_projects: z16.array(z16.number().int().positive()).max(1000).optional(),
2565
- monitors: z16.array(monitorDefinitionSchema).max(MAX_NODE_MONITORS).optional(),
2566
- purged_monitors: z16.array(z16.guid()).max(5000).optional(),
2567
- telemetry: z16.object({
2568
- traces_retention_days: z16.number().int().min(1).max(90),
2569
- logs_retention_days: z16.number().int().min(1).max(90),
2570
- traces_disk_share: z16.number().min(0.2).max(0.8)
3280
+ purged_projects: z20.array(z20.number().int().positive()).max(1000).optional(),
3281
+ monitors: z20.array(monitorDefinitionSchema).max(MAX_NODE_MONITORS).optional(),
3282
+ purged_monitors: z20.array(z20.guid()).max(5000).optional(),
3283
+ telemetry: z20.object({
3284
+ traces_retention_days: z20.number().int().min(1).max(90),
3285
+ logs_retention_days: z20.number().int().min(1).max(90),
3286
+ traces_disk_share: z20.number().min(0.2).max(0.8)
2571
3287
  }).optional(),
2572
- slos: z16.array(nodeSloSchema).max(SLO_LIMITS.maxNodeSlos).optional()
3288
+ slos: z20.array(nodeSloSchema).max(SLO_LIMITS.maxNodeSlos).optional(),
3289
+ signal_monitors: z20.array(signalMonitorDefinitionSchema).max(MAX_NODE_MONITORS).optional(),
3290
+ signal_limits: signalLimitsConfigSchema.optional()
2573
3291
  });
2574
- var signedNodeConfigSchema = z16.object({ config: nodeConfigSchema, kid, sig: z16.string() });
3292
+ var signedNodeConfigSchema = z20.object({ config: nodeConfigSchema, kid, sig: z20.string() });
2575
3293
 
2576
3294
  // ../src/shared/contracts/api-ops/projects.ts
2577
- var slug = z17.string().regex(/^[a-z0-9][a-z0-9-]{1,38}[a-z0-9]$/);
2578
- var name3 = z17.string().trim().min(1).max(60);
2579
- var label = z17.string().trim().min(1).max(40);
2580
- var platform = z17.enum(PLATFORMS);
2581
- var origin = z17.string().trim().toLowerCase().regex(/^https?:\/\/[a-z0-9.-]+(:[0-9]{1,5})?$/).max(200);
2582
- var keyId = z17.number().int().positive();
3295
+ var slug = z21.string().regex(/^[a-z0-9][a-z0-9-]{1,38}[a-z0-9]$/);
3296
+ var name3 = z21.string().trim().min(1).max(60);
3297
+ var label = z21.string().trim().min(1).max(40);
3298
+ var platform = z21.enum(PLATFORMS);
3299
+ var origin = z21.string().trim().toLowerCase().regex(/^https?:\/\/[a-z0-9.-]+(:[0-9]{1,5})?$/).max(200);
3300
+ var keyId = z21.number().int().positive();
2583
3301
  var PROJECT_INPUTS = {
2584
- create: z17.object({ workspaceId: uuid, name: name3, slug, platform }),
2585
- update: z17.object({ projectId, name: name3, platform, isPinned: z17.boolean() }),
2586
- updateIntake: z17.object({
3302
+ create: z21.object({ workspaceId: uuid, name: name3, slug, platform }),
3303
+ update: z21.object({ projectId, name: name3, platform, isPinned: z21.boolean() }),
3304
+ updateIntake: z21.object({
2587
3305
  projectId,
2588
- rateLimit: z17.number().int().positive().nullable(),
2589
- burst: z17.number().int().positive().nullable(),
2590
- allowedOrigins: z17.array(origin).max(50)
3306
+ rateLimit: z21.number().int().positive().nullable(),
3307
+ burst: z21.number().int().positive().nullable(),
3308
+ allowedOrigins: z21.array(origin).max(50)
2591
3309
  }),
2592
- updateObservability: z17.object({
3310
+ updateObservability: z21.object({
2593
3311
  projectId,
2594
- primaryEnvironment: z17.string().trim().min(1).max(64).refine((v) => v !== "*" && ENVIRONMENT_RE.test(v)),
2595
- allowCodeMonitors: z17.boolean()
3312
+ primaryEnvironment: z21.string().trim().min(1).max(64).refine((v) => v !== "*" && ENVIRONMENT_RE.test(v)),
3313
+ allowCodeMonitors: z21.boolean()
2596
3314
  }),
2597
- setScrub: z17.object({ projectId, group: z17.enum(SCRUB_GROUPS), enabled: z17.boolean() }),
2598
- setCheckinAuth: z17.object({ projectId, mode: z17.enum(CHECKIN_AUTH_MODES) }),
2599
- setEnvironmentHidden: z17.object({
3315
+ setScrub: z21.object({ projectId, group: z21.enum(SCRUB_GROUPS), enabled: z21.boolean() }),
3316
+ setCheckinAuth: z21.object({ projectId, mode: z21.enum(CHECKIN_AUTH_MODES) }),
3317
+ setEnvironmentHidden: z21.object({
2600
3318
  projectId,
2601
- name: z17.string().min(1).max(64),
2602
- hidden: z17.boolean()
2603
- }),
2604
- scheduleDeletion: z17.object({ projectId, confirmSlug: slug }),
2605
- projectOnly: z17.object({ projectId }),
2606
- labelled: z17.object({ projectId, label }),
2607
- keyOnly: z17.object({ keyId }),
2608
- tokenOnly: z17.object({ tokenId: keyId }),
3319
+ name: z21.string().min(1).max(64),
3320
+ hidden: z21.boolean()
3321
+ }),
3322
+ scheduleDeletion: z21.object({ projectId, confirmSlug: slug }),
3323
+ projectOnly: z21.object({ projectId }),
3324
+ labelled: z21.object({ projectId, label }),
3325
+ keyOnly: z21.object({ keyId }),
3326
+ tokenOnly: z21.object({ tokenId: keyId }),
2609
3327
  createIngestKey: createIngestKeyInputSchema,
2610
- ingestKeyOnly: z17.object({ keyId: uuid })
3328
+ ingestKeyOnly: z21.object({ keyId: uuid })
2611
3329
  };
2612
3330
  var P = PROJECT_INPUTS;
2613
3331
  var PROJECT_OPERATIONS = [
@@ -2862,23 +3580,28 @@ var PROJECT_OPERATIONS = [
2862
3580
  ];
2863
3581
 
2864
3582
  // ../src/shared/contracts/api-ops/reads.ts
2865
- import { z as z18 } from "zod";
2866
- var list = z18.object({ workspaceId: uuid, limit: pageLimit, cursor });
3583
+ import { z as z22 } from "zod";
3584
+ var list = z22.object({ workspaceId: uuid, limit: pageLimit, cursor });
2867
3585
  var READ_INPUTS = {
2868
- workspace: z18.object({ workspaceId: uuid }),
3586
+ workspace: z22.object({ workspaceId: uuid }),
2869
3587
  list,
2870
- projectsGet: z18.object({ workspaceId: uuid, projectId }),
3588
+ projectsGet: z22.object({ workspaceId: uuid, projectId }),
2871
3589
  monitorsList: list.extend({ projectId: projectId.optional() }),
2872
- monitorsGet: z18.object({ workspaceId: uuid, monitorId: uuid }),
2873
- uptimeGet: z18.object({ workspaceId: uuid, checkId: uuid }),
2874
- slosGet: z18.object({ workspaceId: uuid, sloId: uuid }),
3590
+ monitorsGet: z22.object({ workspaceId: uuid, monitorId: uuid }),
3591
+ uptimeGet: z22.object({ workspaceId: uuid, checkId: uuid }),
3592
+ slosGet: z22.object({ workspaceId: uuid, sloId: uuid }),
2875
3593
  alertsList: list.extend({
2876
- state: z18.enum(["open", "resolved", "all"]).default("all"),
3594
+ state: z22.enum(["open", "resolved", "all"]).default("all"),
2877
3595
  monitorId: uuid.optional()
3596
+ }),
3597
+ approvalsGet: z22.object({ workspaceId: uuid, approvalId: uuid }),
3598
+ monitorsListTyped: list.extend({
3599
+ projectId: projectId.optional(),
3600
+ type: z22.enum(MONITOR_TYPES).optional()
2878
3601
  })
2879
3602
  };
2880
3603
  var R = READ_INPUTS;
2881
- var base = {
3604
+ var base2 = {
2882
3605
  sensitivity: "normal",
2883
3606
  kind: "read",
2884
3607
  method: "GET",
@@ -2888,7 +3611,7 @@ var base = {
2888
3611
  };
2889
3612
  var READ_OPERATIONS = [
2890
3613
  op({
2891
- ...base,
3614
+ ...base2,
2892
3615
  id: "workspace.get",
2893
3616
  path: "/v1/workspace",
2894
3617
  scope: "org:read",
@@ -2898,7 +3621,7 @@ var READ_OPERATIONS = [
2898
3621
  summary: "The token's workspace, plan and the caller's role."
2899
3622
  }),
2900
3623
  op({
2901
- ...base,
3624
+ ...base2,
2902
3625
  id: "members.list",
2903
3626
  path: "/v1/members",
2904
3627
  scope: "members:read",
@@ -2909,7 +3632,7 @@ var READ_OPERATIONS = [
2909
3632
  summary: "Workspace members and their roles."
2910
3633
  }),
2911
3634
  op({
2912
- ...base,
3635
+ ...base2,
2913
3636
  id: "projects.list",
2914
3637
  path: "/v1/projects",
2915
3638
  scope: "projects:read",
@@ -2920,7 +3643,7 @@ var READ_OPERATIONS = [
2920
3643
  summary: "Projects the token can see."
2921
3644
  }),
2922
3645
  op({
2923
- ...base,
3646
+ ...base2,
2924
3647
  id: "projects.get",
2925
3648
  path: "/v1/projects/{project_id}",
2926
3649
  scope: "projects:read",
@@ -2930,18 +3653,18 @@ var READ_OPERATIONS = [
2930
3653
  summary: "One project."
2931
3654
  }),
2932
3655
  op({
2933
- ...base,
3656
+ ...base2,
2934
3657
  id: "monitors.list",
2935
3658
  path: "/v1/monitors",
2936
3659
  scope: "monitors:read",
2937
3660
  rpcs: ["api_read_monitors"],
2938
- input: R.monitorsList,
3661
+ input: R.monitorsListTyped,
2939
3662
  paged: true,
2940
3663
  mcp: "investigate",
2941
- summary: "Cron and heartbeat monitors."
3664
+ summary: "Monitors of every type (cron, heartbeat, count, assertion, deadline, progress); `type` narrows the list."
2942
3665
  }),
2943
3666
  op({
2944
- ...base,
3667
+ ...base2,
2945
3668
  id: "monitors.get",
2946
3669
  path: "/v1/monitors/{monitor_id}",
2947
3670
  scope: "monitors:read",
@@ -2951,7 +3674,7 @@ var READ_OPERATIONS = [
2951
3674
  summary: "One monitor with its ETag."
2952
3675
  }),
2953
3676
  op({
2954
- ...base,
3677
+ ...base2,
2955
3678
  id: "uptime.list",
2956
3679
  path: "/v1/uptime-checks",
2957
3680
  scope: "monitors:read",
@@ -2962,7 +3685,7 @@ var READ_OPERATIONS = [
2962
3685
  summary: "Uptime checks (header values are never returned)."
2963
3686
  }),
2964
3687
  op({
2965
- ...base,
3688
+ ...base2,
2966
3689
  id: "uptime.get",
2967
3690
  path: "/v1/uptime-checks/{check_id}",
2968
3691
  scope: "monitors:read",
@@ -2972,7 +3695,7 @@ var READ_OPERATIONS = [
2972
3695
  summary: "One uptime check."
2973
3696
  }),
2974
3697
  op({
2975
- ...base,
3698
+ ...base2,
2976
3699
  id: "slos.list",
2977
3700
  path: "/v1/slos",
2978
3701
  scope: "monitors:read",
@@ -2983,7 +3706,7 @@ var READ_OPERATIONS = [
2983
3706
  summary: "SLO definitions."
2984
3707
  }),
2985
3708
  op({
2986
- ...base,
3709
+ ...base2,
2987
3710
  id: "slos.get",
2988
3711
  path: "/v1/slos/{slo_id}",
2989
3712
  scope: "monitors:read",
@@ -2993,7 +3716,7 @@ var READ_OPERATIONS = [
2993
3716
  summary: "One SLO definition."
2994
3717
  }),
2995
3718
  op({
2996
- ...base,
3719
+ ...base2,
2997
3720
  id: "alert_rules.list",
2998
3721
  path: "/v1/alert-rules",
2999
3722
  scope: "alerts:read",
@@ -3004,7 +3727,7 @@ var READ_OPERATIONS = [
3004
3727
  summary: "Alert rules."
3005
3728
  }),
3006
3729
  op({
3007
- ...base,
3730
+ ...base2,
3008
3731
  id: "destinations.list",
3009
3732
  path: "/v1/destinations",
3010
3733
  scope: "alerts:read",
@@ -3015,7 +3738,7 @@ var READ_OPERATIONS = [
3015
3738
  summary: "Alert destinations with a masked hint; secrets never leave the server."
3016
3739
  }),
3017
3740
  op({
3018
- ...base,
3741
+ ...base2,
3019
3742
  id: "alerts.list",
3020
3743
  path: "/v1/alerts",
3021
3744
  scope: "alerts:read",
@@ -3026,7 +3749,18 @@ var READ_OPERATIONS = [
3026
3749
  summary: "Alerts: one row per violation episode of a monitor, open or resolved."
3027
3750
  }),
3028
3751
  op({
3029
- ...base,
3752
+ ...base2,
3753
+ id: "maintenance.list",
3754
+ path: "/v1/maintenance-windows",
3755
+ scope: "monitors:read",
3756
+ rpcs: ["api_read_maintenance_windows"],
3757
+ input: R.list,
3758
+ paged: true,
3759
+ mcp: "reliability",
3760
+ summary: "Maintenance windows and whether each is active now."
3761
+ }),
3762
+ op({
3763
+ ...base2,
3030
3764
  id: "node.get",
3031
3765
  path: "/v1/node",
3032
3766
  scope: "org:read",
@@ -3036,7 +3770,7 @@ var READ_OPERATIONS = [
3036
3770
  summary: "The node's state, versions and last heartbeat (null before provisioning)."
3037
3771
  }),
3038
3772
  op({
3039
- ...base,
3773
+ ...base2,
3040
3774
  id: "usage.get",
3041
3775
  path: "/v1/usage",
3042
3776
  scope: "usage:read",
@@ -3046,7 +3780,7 @@ var READ_OPERATIONS = [
3046
3780
  summary: "The workspace's plan and limits."
3047
3781
  }),
3048
3782
  op({
3049
- ...base,
3783
+ ...base2,
3050
3784
  id: "audit.list",
3051
3785
  path: "/v1/audit-log",
3052
3786
  scope: "audit:read",
@@ -3055,6 +3789,16 @@ var READ_OPERATIONS = [
3055
3789
  paged: true,
3056
3790
  mcp: "investigate",
3057
3791
  summary: "Audit log, newest first (admins)."
3792
+ }),
3793
+ op({
3794
+ ...base2,
3795
+ id: "approvals.get",
3796
+ path: "/v1/approvals/{approval_id}",
3797
+ scope: "org:read",
3798
+ rpcs: ["api_read_approval"],
3799
+ input: R.approvalsGet,
3800
+ mcp: "configure",
3801
+ summary: "State of an approval this token asked for (admins: any in the workspace): pending, approved, executed, rejected, expired or failed, with its result ids."
3058
3802
  })
3059
3803
  ];
3060
3804
 
@@ -3064,6 +3808,7 @@ var API_OPERATIONS = [
3064
3808
  ...PROJECT_OPERATIONS,
3065
3809
  ...MONITOR_OPERATIONS,
3066
3810
  ...ALERT_OPERATIONS,
3811
+ ...INCIDENT_OPERATIONS,
3067
3812
  ...ACCESS_OPERATIONS,
3068
3813
  ...NODE_OPERATIONS
3069
3814
  ];
@@ -3071,13 +3816,279 @@ var BY_ID = new Map(API_OPERATIONS.map((o) => [o.id, o]));
3071
3816
  function apiOperation(id) {
3072
3817
  return BY_ID.get(id);
3073
3818
  }
3819
+ function pathParams(path) {
3820
+ return [...path.matchAll(/\{([a-z_]+)\}/g)].map((m) => m[1]);
3821
+ }
3822
+
3823
+ // ../src/shared/contracts/approvals.ts
3824
+ var APPROVAL_STATES = ["pending", "approved", "executed", "rejected", "expired", "failed"];
3825
+ var APPROVAL_LIMITS = {
3826
+ ttlMinutes: 15,
3827
+ stepUpMaxAgeSeconds: 600,
3828
+ pendingPerWorkspace: 20,
3829
+ paramsMaxBytes: 16 * 1024,
3830
+ decisionNoteMax: 500,
3831
+ notifyMaxRecipients: 10
3832
+ };
3833
+ var APPROVAL_APPROVER = {
3834
+ "projects.set_checkin_auth": "admin",
3835
+ "projects.schedule_deletion": "admin",
3836
+ "project_keys.create": "member",
3837
+ "project_keys.rotate": "member",
3838
+ "project_keys.revoke": "member",
3839
+ "upload_tokens.create": "member",
3840
+ "upload_tokens.revoke": "member",
3841
+ "ingest_keys.create": "admin",
3842
+ "ingest_keys.revoke": "admin",
3843
+ "ping_tokens.rotate": "admin",
3844
+ "ping_tokens.revoke_previous": "admin",
3845
+ "ping_tokens.reset": "admin",
3846
+ "destinations.create": "admin",
3847
+ "destinations.update": "admin",
3848
+ "destinations.update_connection": "admin",
3849
+ "destinations.delete": "admin",
3850
+ "destinations.set_recipients": "admin",
3851
+ "members.change_role": "admin",
3852
+ "members.remove": "admin",
3853
+ "invites.create": "admin",
3854
+ "tokens.create_personal": "self",
3855
+ "tokens.create_service": "admin",
3856
+ "tokens.set_policy": "admin",
3857
+ "service_principals.create": "admin",
3858
+ "service_principals.update": "admin",
3859
+ "node.provision": "admin",
3860
+ "node.resize": "admin",
3861
+ "node.schedule_deletion": "owner",
3862
+ "node.set_backup_custody": "owner",
3863
+ "node.rebuild": "owner",
3864
+ "node.submit_recovery_kit": "owner"
3865
+ };
3866
+ var APPROVAL_HUMAN_FIELDS = {
3867
+ "projects.schedule_deletion": ["confirmSlug"],
3868
+ "node.schedule_deletion": ["confirmName"],
3869
+ "node.rebuild": ["confirmName"]
3870
+ };
3871
+ var APPROVAL_SETUP_OPS = ["destinations.create", "destinations.update_connection"];
3872
+ function approvalRequestSchema(operationId, input) {
3873
+ const human = APPROVAL_HUMAN_FIELDS[operationId] ?? [];
3874
+ if (!human.length)
3875
+ return input;
3876
+ return input.omit(Object.fromEntries(human.map((k) => [k, true])));
3877
+ }
3074
3878
 
3075
3879
  // ../src/shared/contracts/api-ops/wire.ts
3076
- import { z as z19 } from "zod";
3880
+ import { z as z23 } from "zod";
3077
3881
  var toSnake = (s) => s.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
3882
+ var toCamel = (s) => s.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase());
3078
3883
  var schemaCache = new WeakMap;
3884
+ function inputJsonSchema(op) {
3885
+ let js = schemaCache.get(op.input);
3886
+ if (!js) {
3887
+ js = z23.toJSONSchema(op.input, { io: "input", unrepresentable: "any" });
3888
+ schemaCache.set(op.input, js);
3889
+ }
3890
+ return js;
3891
+ }
3892
+ function variants(js) {
3893
+ return [js, ...js.anyOf ?? [], ...js.oneOf ?? [], ...js.allOf ?? []];
3894
+ }
3895
+ function propertyMap(js) {
3896
+ const out = new Map;
3897
+ if (!js)
3898
+ return out;
3899
+ for (const v of variants(js)) {
3900
+ for (const [name, schema] of Object.entries(v.properties ?? {}))
3901
+ out.set(toSnake(name), { name, schema });
3902
+ }
3903
+ return out;
3904
+ }
3905
+ function itemSchema(js) {
3906
+ if (!js)
3907
+ return;
3908
+ for (const v of variants(js)) {
3909
+ if (v.items && !Array.isArray(v.items))
3910
+ return v.items;
3911
+ }
3912
+ return;
3913
+ }
3914
+ function isPlainObject(v) {
3915
+ return typeof v === "object" && v !== null && !Array.isArray(v);
3916
+ }
3917
+ function camelize(value, js) {
3918
+ if (Array.isArray(value))
3919
+ return value.map((v) => camelize(v, itemSchema(js)));
3920
+ if (!isPlainObject(value))
3921
+ return value;
3922
+ const props = propertyMap(js);
3923
+ if (props.size === 0)
3924
+ return value;
3925
+ const out = {};
3926
+ for (const [k, v] of Object.entries(value)) {
3927
+ const p = props.get(k);
3928
+ out[p ? p.name : k] = p ? camelize(v, p.schema) : v;
3929
+ }
3930
+ return out;
3931
+ }
3932
+ function snakeSchema(js, drop = []) {
3933
+ const out = { ...js };
3934
+ if (js.properties) {
3935
+ out.properties = Object.fromEntries(Object.entries(js.properties).filter(([k]) => !drop.includes(k)).map(([k, v]) => [toSnake(k), snakeSchema(v)]));
3936
+ if (js.required)
3937
+ out.required = js.required.filter((k) => !drop.includes(k)).map(toSnake);
3938
+ if (out.required && !out.required.length)
3939
+ delete out.required;
3940
+ }
3941
+ if (js.items && !Array.isArray(js.items))
3942
+ out.items = snakeSchema(js.items);
3943
+ for (const key of ["anyOf", "oneOf", "allOf"]) {
3944
+ if (js[key])
3945
+ out[key] = js[key].map((v) => snakeSchema(v, drop));
3946
+ }
3947
+ if (isPlainObject(js.additionalProperties))
3948
+ out.additionalProperties = snakeSchema(js.additionalProperties);
3949
+ return out;
3950
+ }
3951
+ function scalarType(js) {
3952
+ if (!js)
3953
+ return;
3954
+ for (const v of variants(js)) {
3955
+ const t = Array.isArray(v.type) ? v.type.find((x) => x !== "null") : v.type;
3956
+ if (t)
3957
+ return t;
3958
+ }
3959
+ return;
3960
+ }
3961
+ function coerce(raw, js) {
3962
+ const t = scalarType(js);
3963
+ if ((t === "integer" || t === "number") && /^-?\d+(\.\d+)?$/.test(raw))
3964
+ return Number(raw);
3965
+ if (t === "boolean" && (raw === "true" || raw === "false"))
3966
+ return raw === "true";
3967
+ return raw;
3968
+ }
3969
+ function buildOpInput(op, req, workspaceId) {
3970
+ const js = inputJsonSchema(op);
3971
+ const top = propertyMap(js);
3972
+ const out = {};
3973
+ const nested = {};
3974
+ const bodyKey = op.bodyField ? toSnake(op.bodyField) : null;
3975
+ const body = isPlainObject(req.body) ? req.body : req.body === undefined || req.body === null ? {} : null;
3976
+ if (body === null) {
3977
+ out["__invalidBody"] = true;
3978
+ return out;
3979
+ }
3980
+ for (const [k, v] of Object.entries(body)) {
3981
+ const p = top.get(k);
3982
+ if (p && k !== bodyKey)
3983
+ out[p.name] = camelize(v, p.schema);
3984
+ else if (bodyKey)
3985
+ nested[k] = v;
3986
+ else
3987
+ out[k] = v;
3988
+ }
3989
+ if (op.bodyField)
3990
+ out[op.bodyField] = camelize(nested, top.get(bodyKey)?.schema);
3991
+ for (const [k, raw] of Object.entries(req.query)) {
3992
+ const p = top.get(k);
3993
+ if (p)
3994
+ out[p.name] = coerce(raw, p.schema);
3995
+ }
3996
+ for (const name of pathParams(op.path)) {
3997
+ const p = top.get(name);
3998
+ const raw = req.path[name];
3999
+ if (p && raw !== undefined)
4000
+ out[p.name] = coerce(raw, p.schema);
4001
+ }
4002
+ if (op.workspace)
4003
+ out["workspaceId"] = workspaceId;
4004
+ return out;
4005
+ }
4006
+ function wirePointer(op, path) {
4007
+ const segs = path.map((p) => typeof p === "string" ? toSnake(p) : String(p));
4008
+ if (op.bodyField && segs[0] === toSnake(op.bodyField))
4009
+ segs.shift();
4010
+ return `/${segs.map((s) => s.replace(/~/g, "~0").replace(/\//g, "~1")).join("/")}`;
4011
+ }
4012
+ var WIRE_ERRORS_MAX = 20;
4013
+ function wireErrors(op, error) {
4014
+ const flat = (issues, prefix) => issues.flatMap((i) => {
4015
+ if (i.code === "invalid_union" && i.errors && i.errors.length > 0) {
4016
+ const best = i.errors.reduce((a, b) => b.length < a.length ? b : a);
4017
+ if (best.length > 0)
4018
+ return flat(best, [...prefix, ...i.path]);
4019
+ }
4020
+ return [{ ...i, path: [...prefix, ...i.path] }];
4021
+ });
4022
+ return flat(error.issues, []).slice(0, WIRE_ERRORS_MAX).map((i) => ({ pointer: wirePointer(op, i.path), code: i.code }));
4023
+ }
4024
+
4025
+ // ../src/shared/contracts/api-ops/openapi.ts
4026
+ function clean(js) {
4027
+ const { $schema: _drop, ...rest } = js;
4028
+ return rest;
4029
+ }
4030
+ function propertyOf(js, camel) {
4031
+ return clean(snakeSchema(js.properties?.[camel] ?? {}));
4032
+ }
4033
+ function requestSchema(op) {
4034
+ const js = inputJsonSchema(op);
4035
+ const path = pathParams(op.path).map(toCamel);
4036
+ const drop = ["workspaceId", ...path];
4037
+ if (!op.bodyField) {
4038
+ const s = clean(snakeSchema(js, drop));
4039
+ return s.properties && Object.keys(s.properties).length === 0 && !s.anyOf && !s.oneOf ? null : s;
4040
+ }
4041
+ const outer = clean(snakeSchema(js, [...drop, op.bodyField]));
4042
+ const inner = clean(snakeSchema(js.properties?.[op.bodyField] ?? {}));
4043
+ if (!inner.properties)
4044
+ return { allOf: [outer, inner] };
4045
+ return {
4046
+ ...inner,
4047
+ properties: { ...outer.properties ?? {}, ...inner.properties },
4048
+ required: [...outer.required ?? [], ...inner.required ?? []]
4049
+ };
4050
+ }
4051
+ function operationArgsSchema(op, drop = []) {
4052
+ const js = inputJsonSchema(op);
4053
+ const path = pathParams(op.path);
4054
+ const pathProps = Object.fromEntries(path.map((n) => [n, propertyOf(js, toCamel(n))]));
4055
+ const rest = op.method === "GET" ? (() => {
4056
+ const s = clean(snakeSchema(js, ["workspaceId", ...path.map(toCamel)]));
4057
+ return { ...s, required: [] };
4058
+ })() : requestSchema(op);
4059
+ if (rest && !rest.properties) {
4060
+ return { type: "object", properties: pathProps, required: path, allOf: [rest] };
4061
+ }
4062
+ const props = { ...pathProps, ...rest?.properties ?? {} };
4063
+ for (const d of drop)
4064
+ delete props[d];
4065
+ const required = [...path, ...rest?.required ?? []].filter((k) => !drop.includes(k));
4066
+ return {
4067
+ type: "object",
4068
+ properties: props,
4069
+ ...required.length ? { required: [...new Set(required)] } : {},
4070
+ additionalProperties: false
4071
+ };
4072
+ }
3079
4073
 
3080
4074
  // ../src/shared/contracts/mcp-tools.ts
4075
+ function wireFromArgs(op, args) {
4076
+ const names = new Set(pathParams(op.path));
4077
+ const path = {};
4078
+ const query = {};
4079
+ const body = {};
4080
+ for (const [k, v] of Object.entries(args)) {
4081
+ if (v === undefined || v === null)
4082
+ continue;
4083
+ if (names.has(k))
4084
+ path[k] = String(v);
4085
+ else if (op.method === "GET")
4086
+ query[k] = typeof v === "string" ? v : JSON.stringify(v);
4087
+ else
4088
+ body[k] = v;
4089
+ }
4090
+ return { path, query, body: op.method === "GET" ? undefined : body };
4091
+ }
3081
4092
  function wireInput(operationId, opts = {}) {
3082
4093
  const op = apiOperation(operationId);
3083
4094
  if (!op)
@@ -3087,7 +4098,7 @@ function wireInput(operationId, opts = {}) {
3087
4098
  for (const [k, v] of Object.entries(op.input.shape))
3088
4099
  if (!omit.has(k))
3089
4100
  shape[toSnake(k)] = v;
3090
- return z20.object(shape);
4101
+ return z24.object(shape);
3091
4102
  }
3092
4103
  var BUDGETS = [
3093
4104
  { stringBytes: MCP_LIMITS.untrustedStringMaxBytes, listMax: MCP_LIMITS.listMax },
@@ -3177,27 +4188,40 @@ function errorResult(o) {
3177
4188
  }
3178
4189
  };
3179
4190
  }
3180
- var TOOL_OUTPUT_SCHEMA = z20.object({
3181
- untrusted: z20.object({
3182
- data: z20.unknown(),
3183
- provenance: z20.object({
3184
- source: z20.enum(["node", "control_plane", "docs"]),
3185
- operations: z20.array(z20.string())
4191
+ var TOOL_OUTPUT_SCHEMA = z24.object({
4192
+ untrusted: z24.object({
4193
+ data: z24.unknown(),
4194
+ provenance: z24.object({
4195
+ source: z24.enum(["node", "control_plane", "docs"]),
4196
+ operations: z24.array(z24.string())
3186
4197
  })
3187
4198
  }).optional(),
3188
- doc: z20.object({ slug: z20.string(), locale: z20.enum(["en", "vi"]), url: z20.string(), markdown: z20.string(), truncated: z20.boolean() }).optional(),
3189
- results: z20.array(z20.object({ slug: z20.string(), title: z20.string(), description: z20.string(), section: z20.string(), url: z20.string() })).optional(),
3190
- next_cursor: z20.string().nullable().optional(),
3191
- complete: z20.boolean().optional(),
3192
- omitted: z20.array(z20.object({ part: z20.string(), reason: z20.string(), scope: z20.string().optional() })).optional(),
3193
- truncated: z20.literal(true).optional(),
3194
- suspicious_unicode: z20.literal(true).optional(),
3195
- error: z20.object({
3196
- code: z20.string(),
3197
- status: z20.number(),
3198
- detail: z20.string().optional(),
3199
- scope: z20.string().optional(),
3200
- retry_after: z20.number().optional()
4199
+ doc: z24.object({ slug: z24.string(), locale: z24.enum(["en", "vi"]), url: z24.string(), markdown: z24.string(), truncated: z24.boolean() }).optional(),
4200
+ results: z24.array(z24.object({ slug: z24.string(), title: z24.string(), description: z24.string(), section: z24.string(), url: z24.string() })).optional(),
4201
+ next_cursor: z24.string().nullable().optional(),
4202
+ complete: z24.boolean().optional(),
4203
+ omitted: z24.array(z24.object({ part: z24.string(), reason: z24.string(), scope: z24.string().optional() })).optional(),
4204
+ truncated: z24.literal(true).optional(),
4205
+ suspicious_unicode: z24.literal(true).optional(),
4206
+ error: z24.object({
4207
+ code: z24.string(),
4208
+ status: z24.number(),
4209
+ detail: z24.string().optional(),
4210
+ scope: z24.string().optional(),
4211
+ retry_after: z24.number().optional()
4212
+ }).optional(),
4213
+ operations: z24.array(z24.record(z24.string(), z24.unknown())).optional(),
4214
+ operation: z24.record(z24.string(), z24.unknown()).optional(),
4215
+ plan: z24.record(z24.string(), z24.unknown()).optional(),
4216
+ status: z24.enum(["done", "approval_required", "approval_pending", ...APPROVAL_STATES]).optional(),
4217
+ approval: z24.object({
4218
+ approval_id: z24.string(),
4219
+ approval_url: z24.string(),
4220
+ expires_at: z24.string(),
4221
+ state: z24.enum(APPROVAL_STATES),
4222
+ result_code: z24.string().nullable().optional(),
4223
+ result: z24.record(z24.string(), z24.unknown()).optional(),
4224
+ next: z24.string().optional()
3201
4225
  }).optional()
3202
4226
  });
3203
4227
  var spec = (name) => {
@@ -3243,22 +4267,95 @@ var has = (rt, operationId) => {
3243
4267
  return !!op && rt.scopes.includes(op.scope);
3244
4268
  };
3245
4269
  var isoWindow = {
3246
- start: z20.string().max(40).describe("RFC 3339 start of the window, e.g. 2026-10-26T00:00:00Z. Required with end."),
3247
- end: z20.string().max(40).describe("RFC 3339 end of the window. The plan limits its length.")
4270
+ start: z24.string().max(40).describe("RFC 3339 start of the window, e.g. 2026-10-26T00:00:00Z. Required with end."),
4271
+ end: z24.string().max(40).describe("RFC 3339 end of the window. The plan limits its length.")
3248
4272
  };
3249
- var traceIdSchema = z20.string().regex(/^[0-9a-fA-F]{32}$/);
4273
+ var traceIdSchema = z24.string().regex(/^[0-9a-fA-F]{32}$/);
3250
4274
  var MONITOR_KINDS2 = {
3251
4275
  cron: { list: "monitors.list", get: "monitors.get", idField: "monitor_id" },
3252
4276
  uptime: { list: "uptime.list", get: "uptime.get", idField: "check_id" },
3253
4277
  slo: { list: "slos.list", get: "slos.get", idField: "slo_id" }
3254
4278
  };
4279
+ var DESTRUCTIVE_VERBS = new Set([
4280
+ "delete",
4281
+ "revoke",
4282
+ "remove",
4283
+ "schedule_deletion",
4284
+ "rotate",
4285
+ "reset",
4286
+ "revoke_previous",
4287
+ "rebuild",
4288
+ "change_role"
4289
+ ]);
4290
+ function configureOperations() {
4291
+ return API_OPERATIONS.filter((o) => o.mcp === "configure");
4292
+ }
4293
+ function configureOp(id) {
4294
+ if (typeof id !== "string")
4295
+ return null;
4296
+ const op = apiOperation(id);
4297
+ return op && op.mcp === "configure" ? op : null;
4298
+ }
4299
+ function isDestructiveOperation(op) {
4300
+ return op.method === "DELETE" || DESTRUCTIVE_VERBS.has(op.id.slice(op.id.indexOf(".") + 1));
4301
+ }
4302
+ var humanWire = (op) => (APPROVAL_HUMAN_FIELDS[op.id] ?? []).map(toSnake);
4303
+ function resourceRead(op) {
4304
+ if (op.method === "GET")
4305
+ return null;
4306
+ return API_OPERATIONS.find((o) => o.method === "GET" && o.path === op.path && o.kind !== "node") ?? null;
4307
+ }
4308
+ var PLACEHOLDER_WS = "00000000-0000-0000-0000-000000000000";
4309
+ function validateConfigure(op, params) {
4310
+ for (const f of humanWire(op))
4311
+ if (f in params)
4312
+ return { ok: false, errors: [{ pointer: `/${f}`, code: "typed_by_approver" }] };
4313
+ const input = buildOpInput(op, wireFromArgs(op, params), PLACEHOLDER_WS);
4314
+ if (input["__invalidBody"])
4315
+ return { ok: false, errors: [{ pointer: "", code: "object_expected" }] };
4316
+ const schema = op.sensitivity === "approval" ? approvalRequestSchema(op.id, op.input) : op.input;
4317
+ const r = schema.safeParse(input);
4318
+ if (r.success)
4319
+ return { ok: true };
4320
+ return {
4321
+ ok: false,
4322
+ errors: wireErrors(op, r.error)
4323
+ };
4324
+ }
4325
+ function describe(op, scopes) {
4326
+ return {
4327
+ operation_id: op.id,
4328
+ summary: op.summary,
4329
+ method: op.method,
4330
+ path: op.path,
4331
+ scope: op.scope,
4332
+ scope_held: scopes.includes(op.scope),
4333
+ requires_approval: op.sensitivity === "approval",
4334
+ destructive: isDestructiveOperation(op)
4335
+ };
4336
+ }
4337
+ var params = z24.record(z24.string(), z24.unknown()).default({}).describe("Operation fields in wire names (snake_case), as describe_operation's args_schema shows.");
4338
+ var operationIdArg = z24.string().min(3).max(80).describe("An operation id from search_operations, e.g. `monitors.update`.");
4339
+ function approvalBlock(t, next) {
4340
+ return {
4341
+ approval_id: t.approval_id,
4342
+ approval_url: t.approval_url,
4343
+ expires_at: t.expires_at,
4344
+ state: t.state,
4345
+ ...t.result_code !== undefined ? { result_code: t.result_code } : {},
4346
+ ...t.result !== undefined ? { result: t.result } : {},
4347
+ next
4348
+ };
4349
+ }
4350
+ var NEXT_PENDING = "A person with the right role must approve this on belvador.dev (open approval_url; it needs their authenticator code). Nothing has changed yet. Show the link to the user, then call get_operation with approval_id, or apply_change again with the same idempotency_key to get the result.";
4351
+ var NEXT_SETUP = "The approving person also types the secret (bot token, webhook URL, password) on that page; it never passes through the agent.";
3255
4352
  var MCP_TOOL_DEFS = [
3256
4353
  {
3257
4354
  ...spec("get_workspace"),
3258
4355
  title: "Workspace and node",
3259
4356
  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.",
3260
4357
  operations: ["workspace.get", "node.get"],
3261
- input: z20.object({}),
4358
+ input: z24.object({}),
3262
4359
  async run(_args, rt) {
3263
4360
  const [ws, node] = await Promise.all([rt.call("workspace.get", {}), rt.call("node.get", {})]);
3264
4361
  if (!ws.ok)
@@ -3276,9 +4373,9 @@ var MCP_TOOL_DEFS = [
3276
4373
  title: "Get an issue",
3277
4374
  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).",
3278
4375
  operations: ["issues.get", "events.get"],
3279
- input: z20.object({
3280
- issue_id: z20.number().int().positive().describe("Issue id from search_issues."),
3281
- include_latest_event: z20.boolean().default(true)
4376
+ input: z24.object({
4377
+ issue_id: z24.number().int().positive().describe("Issue id from search_issues."),
4378
+ include_latest_event: z24.boolean().default(true)
3282
4379
  }),
3283
4380
  async run(args, rt) {
3284
4381
  const omitted = [];
@@ -3306,9 +4403,9 @@ var MCP_TOOL_DEFS = [
3306
4403
  title: "Get a trace",
3307
4404
  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).",
3308
4405
  operations: ["traces.get", "traces.spans"],
3309
- input: z20.object({
4406
+ input: z24.object({
3310
4407
  trace_id: traceIdSchema.describe("W3C trace id, 32 hex characters."),
3311
- spans: z20.enum(["none", "errors", "all"]).default("none")
4408
+ spans: z24.enum(["none", "errors", "all"]).default("none")
3312
4409
  }),
3313
4410
  async run(args, rt) {
3314
4411
  const sum = await rt.call("traces.get", { trace_id: args["trace_id"] });
@@ -3336,11 +4433,11 @@ var MCP_TOOL_DEFS = [
3336
4433
  title: "Correlate by trace or run",
3337
4434
  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.",
3338
4435
  operations: ["traces.get", "traces.spans", "spans.list", "logs.list"],
3339
- input: z20.object({
4436
+ input: z24.object({
3340
4437
  trace_id: traceIdSchema.optional(),
3341
- run_id: z20.string().min(1).max(128).optional(),
4438
+ run_id: z24.string().min(1).max(128).optional(),
3342
4439
  ...isoWindow,
3343
- project: z20.string().max(2000).optional().describe("Comma-separated project ids.")
4440
+ project: z24.string().max(2000).optional().describe("Comma-separated project ids.")
3344
4441
  }),
3345
4442
  async run(args, rt) {
3346
4443
  const trace = args["trace_id"];
@@ -3383,12 +4480,12 @@ var MCP_TOOL_DEFS = [
3383
4480
  {
3384
4481
  ...spec("list_monitors"),
3385
4482
  title: "List monitors",
3386
- description: "Cron/heartbeat monitors, uptime checks and SLOs with their current status. `kind` narrows to one family; `project_id` to one project (cron and uptime).",
4483
+ 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).",
3387
4484
  operations: ["monitors.list", "uptime.list", "slos.list"],
3388
- input: z20.object({
3389
- kind: z20.enum(["all", "cron", "uptime", "slo"]).default("all"),
3390
- project_id: z20.number().int().positive().optional(),
3391
- limit: z20.number().int().min(1).max(200).default(50)
4485
+ input: z24.object({
4486
+ kind: z24.enum(["all", "cron", "uptime", "slo"]).default("all"),
4487
+ project_id: z24.number().int().positive().optional(),
4488
+ limit: z24.number().int().min(1).max(200).default(50)
3392
4489
  }),
3393
4490
  async run(args, rt) {
3394
4491
  const kinds = args["kind"] && args["kind"] !== "all" ? [args["kind"]] : ["cron", "uptime", "slo"];
@@ -3414,26 +4511,69 @@ var MCP_TOOL_DEFS = [
3414
4511
  {
3415
4512
  ...spec("get_monitor_status"),
3416
4513
  title: "Get a monitor",
3417
- description: "One cron monitor, uptime check or SLO by id: settings, current status and recent results.",
3418
- operations: ["monitors.get", "uptime.get", "slos.get"],
3419
- input: z20.object({ kind: z20.enum(["cron", "uptime", "slo"]), id: z20.guid() }),
4514
+ 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.",
4515
+ operations: ["monitors.get", "uptime.get", "slos.get", "monitors.signal", "monitors.occurrences", "monitors.backtest"],
4516
+ input: z24.object({
4517
+ kind: z24.enum(["cron", "uptime", "slo"]),
4518
+ id: z24.guid(),
4519
+ backtest: z24.boolean().default(false)
4520
+ }),
3420
4521
  async run(args, rt) {
3421
4522
  const k = MONITOR_KINDS2[args["kind"]];
3422
4523
  const r = await rt.call(k.get, { [k.idField]: args["id"] });
3423
4524
  if (!r.ok)
3424
4525
  return errorResult(r);
3425
- return wrapResult({ data: r.body, operations: [k.get], source: "control_plane" });
4526
+ const row = r.body ?? {};
4527
+ const type = typeof row["type"] === "string" ? row["type"] : "job";
4528
+ if (k.get !== "monitors.get" || !isSignalMonitorType(type)) {
4529
+ return wrapResult({ data: r.body, operations: [k.get], source: "control_plane" });
4530
+ }
4531
+ const ops = [k.get, "monitors.signal"];
4532
+ const calls = [
4533
+ rt.call("monitors.signal", { monitor_id: args["id"], hours: 24 })
4534
+ ];
4535
+ const parts = ["signal"];
4536
+ if (type === "deadline") {
4537
+ ops.push("monitors.occurrences");
4538
+ parts.push("occurrences");
4539
+ calls.push(rt.call("monitors.occurrences", { monitor_id: args["id"], state: "all" }));
4540
+ }
4541
+ const settings = args["backtest"] === true && (type === "count" || type === "assertion") ? settingsFromRow({
4542
+ type,
4543
+ signal_settings: row["signal_settings"],
4544
+ expected_environments: Array.isArray(row["expected_environments"]) ? row["expected_environments"] : [],
4545
+ severity: String(row["severity"] ?? "medium"),
4546
+ recovery_threshold: Number(row["recovery_threshold"] ?? 1)
4547
+ }) : null;
4548
+ if (settings) {
4549
+ ops.push("monitors.backtest");
4550
+ parts.push("backtest");
4551
+ calls.push(rt.call("monitors.backtest", { project: row["project_id"], settings }));
4552
+ }
4553
+ const answers = await Promise.all(calls);
4554
+ const data = { monitor: r.body };
4555
+ const omitted = [];
4556
+ for (const [i, part] of parts.entries()) {
4557
+ const a = answers[i];
4558
+ if (a.ok)
4559
+ data[part] = part === "occurrences" ? withoutPaging(a.body) : a.body;
4560
+ else
4561
+ omitted.push({ part, reason: a.code });
4562
+ }
4563
+ return wrapResult({ data, operations: ops, source: omitted.length === parts.length ? "control_plane" : "node" }, { omitted });
3426
4564
  }
3427
4565
  },
3428
4566
  single("list_alerts", "alerts.list", "List alerts", "Alerts Belvador raised (open, resolved or all), newest first, optionally for one monitor."),
4567
+ single("list_incidents", "incidents.list", "List incidents", "Incidents (INC-n): related alerts grouped into one piece of work. State (open, acknowledged, monitoring, resolved), severity and peak, owner, linked and still-firing alert counts; newest first. `state` = active, resolved or all. Returns ids for get_incident."),
4568
+ single("get_incident", "incidents.get", "Get an incident", "One incident by id: its linked alerts (monitor, uptime, SLO, issue) with ids for get_monitor_status or get_issue, the timeline (opened, joined, acknowledged, notes, escalation, resolution) and each message's delivery state. `accepted` means the service took the message; only `acknowledged: true` means a person took the incident."),
3429
4569
  {
3430
4570
  ...spec("verify_integration"),
3431
4571
  title: "Send a test event",
3432
4572
  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).",
3433
4573
  operations: ["projects.send_test_event"],
3434
- input: z20.object({
3435
- project_id: z20.number().int().positive(),
3436
- idempotency_key: z20.string().min(8).max(255).optional()
4574
+ input: z24.object({
4575
+ project_id: z24.number().int().positive(),
4576
+ idempotency_key: z24.string().min(8).max(255).optional()
3437
4577
  }),
3438
4578
  async run(args, rt) {
3439
4579
  const r = await rt.call("projects.send_test_event", { project_id: args["project_id"] }, { idempotencyKey: args["idempotency_key"] ?? rt.newKey() });
@@ -3442,15 +4582,198 @@ var MCP_TOOL_DEFS = [
3442
4582
  return wrapResult({ data: r.body, operations: ["projects.send_test_event"], source: "control_plane" });
3443
4583
  }
3444
4584
  },
4585
+ {
4586
+ ...spec("search_operations"),
4587
+ title: "Find a configuration change",
4588
+ 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.",
4589
+ operations: [],
4590
+ input: z24.object({
4591
+ query: z24.string().min(1).max(200).describe("Words such as `rotate dsn key`, `heartbeat monitor`, `slack alert`."),
4592
+ limit: z24.number().int().min(1).max(20).default(10)
4593
+ }),
4594
+ async run(args, rt) {
4595
+ const q = words(String(args["query"]));
4596
+ const scored = configureOperations().filter((o) => o.method !== "GET").map((o) => {
4597
+ const id = words(o.id.replace(/[._]/g, " "));
4598
+ const rest = words(`${o.summary} ${o.path}`);
4599
+ let score = 0;
4600
+ for (const w of q) {
4601
+ if (id.some((t) => t === w))
4602
+ score += 4;
4603
+ else if (id.some((t) => t.startsWith(w)))
4604
+ score += 2;
4605
+ if (rest.some((t) => t === w))
4606
+ score += 2;
4607
+ else if (rest.some((t) => t.startsWith(w)))
4608
+ score += 1;
4609
+ }
4610
+ return { o, score };
4611
+ }).filter((x) => x.score > 0).sort((a, b) => b.score - a.score || a.o.id.localeCompare(b.o.id)).slice(0, Number(args["limit"] ?? 10));
4612
+ return { structuredContent: { operations: scored.map((x) => describe(x.o, rt.scopes)) } };
4613
+ }
4614
+ },
4615
+ {
4616
+ ...spec("describe_operation"),
4617
+ title: "Describe a configuration change",
4618
+ 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.",
4619
+ operations: [],
4620
+ input: z24.object({ operation_id: operationIdArg }),
4621
+ async run(args, rt) {
4622
+ const op = configureOp(args["operation_id"]);
4623
+ if (!op || op.method === "GET")
4624
+ return errorResult({ ok: false, status: 404, code: "NOT_FOUND" });
4625
+ const approval = op.sensitivity === "approval";
4626
+ return {
4627
+ structuredContent: {
4628
+ operation: {
4629
+ ...describe(op, rt.scopes),
4630
+ idempotency: op.idempotency,
4631
+ if_match_required: !!op.ifMatch,
4632
+ args_schema: operationArgsSchema(op, humanWire(op)),
4633
+ ...approval ? {
4634
+ approver: APPROVAL_APPROVER[op.id] ?? "admin",
4635
+ typed_by_approver: humanWire(op),
4636
+ secrets_typed_by_approver: APPROVAL_SETUP_OPS.includes(op.id)
4637
+ } : {},
4638
+ ...op.secretOutput?.length ? { secret_output: [...op.secretOutput] } : {}
4639
+ }
4640
+ }
4641
+ };
4642
+ }
4643
+ },
4644
+ {
4645
+ ...spec("plan_change"),
4646
+ title: "Check a change before applying it",
4647
+ 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.",
4648
+ operations: [],
4649
+ input: z24.object({ operation_id: operationIdArg, params }),
4650
+ async run(args, rt) {
4651
+ const op = configureOp(args["operation_id"]);
4652
+ if (!op || op.method === "GET")
4653
+ return errorResult({ ok: false, status: 404, code: "NOT_FOUND" });
4654
+ const p = args["params"] ?? {};
4655
+ const v = validateConfigure(op, p);
4656
+ const scopeMissing = rt.scopes.includes(op.scope) ? [] : [op.scope];
4657
+ let etag = null;
4658
+ let current = undefined;
4659
+ const read = resourceRead(op);
4660
+ const ids = read ? Object.fromEntries(pathParams(read.path).map((n) => [n, p[n]])) : {};
4661
+ if (read && rt.scopes.includes(read.scope) && Object.values(ids).every((x) => x != null && x !== "")) {
4662
+ const r = await rt.call(read.id, ids);
4663
+ if (r.ok) {
4664
+ etag = r.etag ?? null;
4665
+ current = r.body;
4666
+ }
4667
+ }
4668
+ const changes = Object.entries(p).filter(([k]) => !pathParams(op.path).includes(k)).map(([field, to]) => {
4669
+ const cur = current && typeof current === "object" && !Array.isArray(current) ? current : null;
4670
+ return cur && field in cur ? { field, from: cur[field], to } : { field, to };
4671
+ });
4672
+ const plan = {
4673
+ operation_id: op.id,
4674
+ valid: v.ok,
4675
+ ...v.ok ? {} : { errors: v.errors },
4676
+ scope: op.scope,
4677
+ scope_missing: scopeMissing,
4678
+ requires_approval: op.sensitivity === "approval",
4679
+ ...op.sensitivity === "approval" ? { approver: APPROVAL_APPROVER[op.id] ?? "admin" } : {},
4680
+ destructive: isDestructiveOperation(op),
4681
+ idempotency: op.idempotency,
4682
+ if_match_required: !!op.ifMatch,
4683
+ etag
4684
+ };
4685
+ const out = wrapResult({
4686
+ data: { changes, ...current !== undefined ? { current } : {} },
4687
+ operations: read && current !== undefined ? [read.id] : [],
4688
+ source: "control_plane"
4689
+ });
4690
+ return { structuredContent: { plan, ...out.structuredContent } };
4691
+ }
4692
+ },
4693
+ {
4694
+ ...spec("apply_change"),
4695
+ title: "Apply a configuration change",
4696
+ 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.",
4697
+ operations: [],
4698
+ input: z24.object({
4699
+ operation_id: operationIdArg,
4700
+ params,
4701
+ idempotency_key: z24.string().min(8).max(255).describe("Unique per change; reuse it to retry or to fetch the result."),
4702
+ if_match: z24.string().max(200).optional().describe("ETag from plan_change, for operations that need it.")
4703
+ }),
4704
+ async run(args, rt) {
4705
+ const op = configureOp(args["operation_id"]);
4706
+ if (!op || op.method === "GET")
4707
+ return errorResult({ ok: false, status: 404, code: "NOT_FOUND" });
4708
+ const p = args["params"] ?? {};
4709
+ for (const f of humanWire(op))
4710
+ if (f in p)
4711
+ return errorResult({ ok: false, status: 400, code: "INVALID_INPUT", detail: `${f} is typed by the approving person` });
4712
+ const opts = { idempotencyKey: String(args["idempotency_key"]) };
4713
+ if (typeof args["if_match"] === "string" && args["if_match"])
4714
+ opts.ifMatch = args["if_match"];
4715
+ const r = await rt.call(op.id, p, opts);
4716
+ if (r.ok) {
4717
+ const body = r.body;
4718
+ if (op.sensitivity === "approval" && body && typeof body["approval_id"] === "string") {
4719
+ return {
4720
+ structuredContent: {
4721
+ status: "executed",
4722
+ approval: approvalBlock(body, "Approved and run once by a person; result holds the ids.")
4723
+ }
4724
+ };
4725
+ }
4726
+ const out = wrapResult({ data: r.body, operations: [op.id], source: sourceOf(op.id) });
4727
+ return { structuredContent: { status: "done", ...out.structuredContent } };
4728
+ }
4729
+ if (r.approval && r.approval.state === "pending") {
4730
+ const next = APPROVAL_SETUP_OPS.includes(op.id) ? `${NEXT_PENDING} ${NEXT_SETUP}` : NEXT_PENDING;
4731
+ return {
4732
+ structuredContent: { status: "approval_required", approval: approvalBlock(r.approval, next) },
4733
+ approval: r.approval
4734
+ };
4735
+ }
4736
+ if (r.approval) {
4737
+ return {
4738
+ isError: true,
4739
+ structuredContent: {
4740
+ ...errorResult(r).structuredContent,
4741
+ approval: approvalBlock(r.approval, "This request is closed; send a new one with a new idempotency_key if the change is still wanted.")
4742
+ }
4743
+ };
4744
+ }
4745
+ return errorResult(r);
4746
+ }
4747
+ },
4748
+ {
4749
+ ...spec("get_operation"),
4750
+ title: "Follow an approval",
4751
+ 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).",
4752
+ operations: ["approvals.get"],
4753
+ input: z24.object({ approval_id: z24.guid().describe("approval_id from apply_change.") }),
4754
+ async run(args, rt) {
4755
+ const r = await rt.call("approvals.get", { approval_id: args["approval_id"] });
4756
+ if (!r.ok)
4757
+ return errorResult(r);
4758
+ const b = r.body;
4759
+ const next = b.state === "pending" ? NEXT_PENDING : b.state === "executed" ? "Done: the change ran once." : b.state === "approved" ? "Approved; the change is running or waits for the person to finish the form." : "Closed without a change.";
4760
+ return {
4761
+ structuredContent: {
4762
+ status: b.state,
4763
+ approval: approvalBlock({ ...b, approval_url: b.approval_url ?? "" }, next)
4764
+ }
4765
+ };
4766
+ }
4767
+ },
3445
4768
  {
3446
4769
  ...spec("search_docs"),
3447
4770
  title: "Search Belvador docs",
3448
4771
  description: "Searches the public Belvador documentation (titles and summaries) and returns the best pages with their slugs for get_doc.",
3449
4772
  operations: [],
3450
- input: z20.object({
3451
- query: z20.string().min(1).max(200),
3452
- locale: z20.enum(["en", "vi"]).default("en"),
3453
- limit: z20.number().int().min(1).max(10).default(5)
4773
+ input: z24.object({
4774
+ query: z24.string().min(1).max(200),
4775
+ locale: z24.enum(["en", "vi"]).default("en"),
4776
+ limit: z24.number().int().min(1).max(10).default(5)
3454
4777
  }),
3455
4778
  async run(args, rt) {
3456
4779
  const locale = args["locale"] ?? "en";
@@ -3466,9 +4789,9 @@ var MCP_TOOL_DEFS = [
3466
4789
  title: "Read a docs page",
3467
4790
  description: "The Markdown of one public Belvador docs page by slug (e.g. `quickstart`, `sdk/react`, `reference/api`).",
3468
4791
  operations: [],
3469
- input: z20.object({
3470
- slug: z20.string().regex(/^[a-z0-9][a-z0-9/-]{0,120}$/),
3471
- locale: z20.enum(["en", "vi"]).default("en")
4792
+ input: z24.object({
4793
+ slug: z24.string().regex(/^[a-z0-9][a-z0-9/-]{0,120}$/),
4794
+ locale: z24.enum(["en", "vi"]).default("en")
3472
4795
  }),
3473
4796
  async run(args, rt) {
3474
4797
  const locale = args["locale"] ?? "en";
@@ -3542,6 +4865,12 @@ function toolsFor(toolsets, scopes) {
3542
4865
 
3543
4866
  // ../src/shared/mcp/server.ts
3544
4867
  var MCP_SERVER_VERSION = `1.${MCP_TOOLS_VERSION}.0`;
4868
+ var APPROVAL_ELICIT_MESSAGE = "Belvador needs a person to approve this change. Open the link, review it and confirm with your authenticator code; then the agent continues.";
4869
+ function wantsApprovalLink(ctx) {
4870
+ const env = ctx?.mcpReq.envelope;
4871
+ const caps = env?.[CLIENT_CAPABILITIES_META_KEY];
4872
+ return !!caps?.elicitation?.url && !ctx?.mcpReq.inputResponses?.["approval"];
4873
+ }
3545
4874
  function buildMcpServer(rt, toolsets) {
3546
4875
  const server = new McpServer({ name: "belvador", title: "Belvador", version: MCP_SERVER_VERSION }, { instructions: MCP_SERVER_INSTRUCTIONS });
3547
4876
  for (const t of toolsFor([...toolsets], rt.scopes)) {
@@ -3557,8 +4886,15 @@ function buildMcpServer(rt, toolsets) {
3557
4886
  idempotentHint: t.idempotent,
3558
4887
  openWorldHint: false
3559
4888
  }
3560
- }, async (args) => {
4889
+ }, async (args, ctx) => {
3561
4890
  const r = await t.run(args, rt);
4891
+ if (r.approval && r.approval.state === "pending" && wantsApprovalLink(ctx)) {
4892
+ return inputRequired({
4893
+ inputRequests: {
4894
+ approval: inputRequired.elicitUrl({ message: APPROVAL_ELICIT_MESSAGE, url: r.approval.approval_url })
4895
+ }
4896
+ });
4897
+ }
3562
4898
  return {
3563
4899
  content: [{ type: "text", text: JSON.stringify(r.structuredContent) }],
3564
4900
  structuredContent: r.structuredContent,
@@ -3579,7 +4915,15 @@ function outcomeOfError(e) {
3579
4915
  code: e.code === "ABORTED" ? "UNAVAILABLE" : e.code,
3580
4916
  ...e.detail ? { detail: e.detail } : {},
3581
4917
  ...e.scope ? { scope: e.scope } : {},
3582
- ...e.retryAfter ? { retryAfter: e.retryAfter } : {}
4918
+ ...e.retryAfter ? { retryAfter: e.retryAfter } : {},
4919
+ ...e.approval ? {
4920
+ approval: {
4921
+ approval_id: e.approval.id,
4922
+ approval_url: e.approval.url,
4923
+ expires_at: e.approval.expiresAt,
4924
+ state: e.approval.state
4925
+ }
4926
+ } : {}
3583
4927
  };
3584
4928
  return { ok: false, status: 503, code: "UNAVAILABLE" };
3585
4929
  }
@@ -3591,8 +4935,13 @@ function clientRuntime(client, scopes, docs) {
3591
4935
  async call(operationId, args, opts) {
3592
4936
  try {
3593
4937
  const call = client.call.bind(client);
3594
- const r = await call(operationId, args, opts?.idempotencyKey ? { idempotencyKey: opts.idempotencyKey } : {});
3595
- return { ok: true, status: r.status, body: r.data };
4938
+ const o = {};
4939
+ if (opts?.idempotencyKey)
4940
+ o.idempotencyKey = opts.idempotencyKey;
4941
+ if (opts?.ifMatch)
4942
+ o.ifMatch = opts.ifMatch;
4943
+ const r = await call(operationId, args, o);
4944
+ return { ok: true, status: r.status, body: r.data, etag: r.etag };
3596
4945
  } catch (e) {
3597
4946
  return outcomeOfError(e);
3598
4947
  }
@@ -3624,7 +4973,7 @@ function findToken(env = process.env, keychain = keychainToken) {
3624
4973
  }
3625
4974
 
3626
4975
  // packages/mcp/src/cli.ts
3627
- var PACKAGE_VERSION = "0.1.0";
4976
+ var PACKAGE_VERSION = "0.3.0";
3628
4977
  var HELP = `belvador-mcp ${PACKAGE_VERSION} — Belvador MCP server (stdio)
3629
4978
 
3630
4979
  Usage: npx -y @belvador/mcp [--toolsets=${MCP_DEFAULT_TOOLSETS.join(",")}]