@neat.is/core 0.9.8-dev.20260828 → 0.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.cjs CHANGED
@@ -787,7 +787,7 @@ function getGraph(project = DEFAULT_PROJECT) {
787
787
  init_cjs_shims();
788
788
  var import_fastify2 = __toESM(require("fastify"), 1);
789
789
  var import_cors = __toESM(require("@fastify/cors"), 1);
790
- var import_types97 = require("@neat.is/types");
790
+ var import_types98 = require("@neat.is/types");
791
791
 
792
792
  // src/extend/index.ts
793
793
  init_cjs_shims();
@@ -5596,11 +5596,25 @@ function upsertInferredEdge(graph, type, source, target, ts) {
5596
5596
  };
5597
5597
  graph.addEdgeWithKey(id, source, target, edge);
5598
5598
  }
5599
+ function emitIncidentEvent(project, ev) {
5600
+ emitNeatEvent({
5601
+ type: "incident",
5602
+ project,
5603
+ payload: {
5604
+ incidentId: ev.id,
5605
+ affectedNode: ev.affectedNode,
5606
+ service: ev.service,
5607
+ incidentKind: (0, import_types7.incidentKindOf)(ev),
5608
+ at: ev.timestamp
5609
+ }
5610
+ });
5611
+ }
5599
5612
  async function appendErrorEvent(ctx, ev) {
5600
5613
  await import_node_fs9.promises.mkdir(import_node_path10.default.dirname(ctx.errorsPath), { recursive: true });
5601
5614
  await import_node_fs9.promises.appendFile(ctx.errorsPath, JSON.stringify(ev) + "\n", "utf8");
5615
+ emitIncidentEvent(ctx.project ?? DEFAULT_PROJECT, ev);
5602
5616
  }
5603
- async function appendConnectorIncident(errorsPath, input) {
5617
+ async function appendConnectorIncident(errorsPath, input, project) {
5604
5618
  const ev = {
5605
5619
  id: input.id,
5606
5620
  timestamp: input.timestamp,
@@ -5614,6 +5628,7 @@ async function appendConnectorIncident(errorsPath, input) {
5614
5628
  };
5615
5629
  await import_node_fs9.promises.mkdir(import_node_path10.default.dirname(errorsPath), { recursive: true });
5616
5630
  await import_node_fs9.promises.appendFile(errorsPath, JSON.stringify(ev) + "\n", "utf8");
5631
+ if (project) emitIncidentEvent(project, ev);
5617
5632
  }
5618
5633
  function landIncidentCallSite(span, callSite, trusted, graph) {
5619
5634
  const relPath = graph ? reconcileObservedRelPath(graph, span.service, callSite.relPath) : callSite.relPath;
@@ -16867,9 +16882,128 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
16867
16882
  return result;
16868
16883
  }
16869
16884
 
16870
- // src/ask.ts
16885
+ // src/goodybag.ts
16871
16886
  init_cjs_shims();
16872
16887
  var import_types58 = require("@neat.is/types");
16888
+ var CODE_FILEPATH_ATTR2 = "code.filepath";
16889
+ var CODE_LINENO_ATTR2 = "code.lineno";
16890
+ var BLAST_NEAREST_LIMIT = 5;
16891
+ function grainOf2(graph, nodeId) {
16892
+ if (graph.hasNode(nodeId)) {
16893
+ const t = graph.getNodeAttributes(nodeId).type;
16894
+ if (typeof t === "string" && t.length > 0) {
16895
+ return (t.endsWith("Node") ? t.slice(0, -4) : t).toLowerCase();
16896
+ }
16897
+ }
16898
+ const colon = nodeId.indexOf(":");
16899
+ return colon > 0 ? nodeId.slice(0, colon) : "unknown";
16900
+ }
16901
+ function locusOf(graph, ev) {
16902
+ const file = ev.attributes?.[CODE_FILEPATH_ATTR2];
16903
+ if (typeof file !== "string" || file.length === 0) return null;
16904
+ const rawLine = ev.attributes?.[CODE_LINENO_ATTR2];
16905
+ const line = typeof rawLine === "number" ? rawLine : Number(rawLine);
16906
+ const node = graph.hasNode(ev.affectedNode) ? graph.getNodeAttributes(ev.affectedNode) : void 0;
16907
+ return {
16908
+ file,
16909
+ ...Number.isFinite(line) ? { lineStart: line, lineEnd: line } : {},
16910
+ ...node?.name ? { symbol: node.name } : {},
16911
+ service: node?.service ?? ev.service,
16912
+ provenance: import_types58.Provenance.OBSERVED
16913
+ };
16914
+ }
16915
+ function divergenceSummary(d) {
16916
+ const column = "column" in d && d.column ? `.${d.column}` : "";
16917
+ const label = "table" in d && d.table ? `${d.table}${column}` : `${d.source} \u2192 ${d.target}`;
16918
+ return label;
16919
+ }
16920
+ function baseName(p) {
16921
+ const parts = p.split(/[\\/]/);
16922
+ return parts[parts.length - 1] || p;
16923
+ }
16924
+ function shortLabel(graph, nodeId) {
16925
+ if (graph.hasNode(nodeId)) {
16926
+ const name = graph.getNodeAttributes(nodeId).name;
16927
+ if (typeof name === "string" && name.length > 0) return name;
16928
+ }
16929
+ const afterHash = nodeId.includes("#") ? nodeId.slice(nodeId.lastIndexOf("#") + 1) : nodeId;
16930
+ return afterHash.includes(":") ? afterHash.slice(afterHash.lastIndexOf(":") + 1) : afterHash;
16931
+ }
16932
+ function renderHeadline(graph, ev, locus, causeNode) {
16933
+ const what = ev.exceptionType ? `raised ${ev.exceptionType}` : ev.errorMessage || "failed";
16934
+ const cause = causeNode && causeNode !== ev.affectedNode ? ` \u2192 root cause ${shortLabel(graph, causeNode)}` : "";
16935
+ if (locus) {
16936
+ const base = baseName(locus.file);
16937
+ const lines = locus.lineStart != null ? locus.lineEnd && locus.lineEnd !== locus.lineStart ? `LINES ${locus.lineStart}-${locus.lineEnd}` : `LINE ${locus.lineStart}` : "";
16938
+ const symbol = locus.symbol ?? (grainOf2(graph, ev.affectedNode) === "symbol" ? shortLabel(graph, ev.affectedNode) : void 0);
16939
+ const subject = symbol ? `SYMBOL ${symbol}` : `FILE ${base}`;
16940
+ const at = symbol ? `${lines ? `${lines} in ` : ""}${base}` : lines;
16941
+ const where = at ? ` at ${at}` : "";
16942
+ return `${subject}${where} (SERVICE ${ev.service}) ${what} at ${ev.timestamp}${cause}`;
16943
+ }
16944
+ return `SERVICE ${ev.service} ${what} at ${ev.timestamp}${cause}`;
16945
+ }
16946
+ function buildIncidentCard(graph, errorEvent, incidents, policies) {
16947
+ const affected = errorEvent.affectedNode;
16948
+ const locus = locusOf(graph, errorEvent);
16949
+ const inGraph = graph.hasNode(affected);
16950
+ const rc = inGraph ? getRootCause(graph, affected, errorEvent, incidents) : null;
16951
+ let rootCause = null;
16952
+ if (rc) {
16953
+ const provs = rc.edgeProvenances ?? [];
16954
+ const chain = (rc.traversalPath ?? []).map((node, i) => ({
16955
+ node,
16956
+ grain: grainOf2(graph, node),
16957
+ provenance: provs[i] ?? provs[provs.length - 1] ?? import_types58.Provenance.INFERRED
16958
+ }));
16959
+ rootCause = {
16960
+ node: rc.rootCauseNode,
16961
+ ...rc.candidates?.[0]?.classification ? { classification: rc.candidates[0].classification } : {},
16962
+ reason: rc.rootCauseReason,
16963
+ confidence: rc.confidence,
16964
+ fix: rc.fixRecommendation ?? null,
16965
+ chain
16966
+ };
16967
+ }
16968
+ const blast = inGraph ? getBlastRadius(graph, affected) : { origin: affected, affectedNodes: [], totalAffected: 0 };
16969
+ const nearest = [...blast.affectedNodes].sort((a, b) => a.distance - b.distance).slice(0, BLAST_NEAREST_LIMIT).map((n) => ({ node: n.nodeId, distance: n.distance, provenance: n.edgeProvenance }));
16970
+ const applicable = inGraph ? selectApplicablePolicies(graph, policies, affected) : [];
16971
+ const policyCards = applicable.map((p) => ({
16972
+ policyName: p.policyName,
16973
+ severity: p.severity,
16974
+ message: p.reason
16975
+ }));
16976
+ const divergences = inGraph ? computeDivergences(graph, { node: affected, incidents }).divergences.map((d) => ({
16977
+ type: d.type,
16978
+ summary: divergenceSummary(d)
16979
+ })) : [];
16980
+ const card = {
16981
+ kind: "incident",
16982
+ id: errorEvent.id,
16983
+ at: errorEvent.timestamp,
16984
+ incidentKind: (0, import_types58.incidentKindOf)(errorEvent),
16985
+ service: errorEvent.service,
16986
+ affectedNode: affected,
16987
+ message: errorEvent.errorMessage,
16988
+ ...errorEvent.exceptionType ? { exceptionType: errorEvent.exceptionType } : {},
16989
+ ...errorEvent.httpStatusCode !== void 0 ? { httpStatusCode: errorEvent.httpStatusCode } : {},
16990
+ ...errorEvent.incidentCount !== void 0 ? { count: errorEvent.incidentCount } : {},
16991
+ ...errorEvent.firstTimestamp && errorEvent.lastTimestamp ? { window: { first: errorEvent.firstTimestamp, last: errorEvent.lastTimestamp } } : {},
16992
+ ...errorEvent.traceId ? { traceId: errorEvent.traceId } : {},
16993
+ ...errorEvent.spanId ? { spanId: errorEvent.spanId } : {},
16994
+ locus,
16995
+ rootCause,
16996
+ ...nearest.length > 0 ? { blastRadius: { totalAffected: blast.totalAffected, nearest } } : {},
16997
+ ...policyCards.length > 0 ? { policies: policyCards } : {},
16998
+ ...divergences.length > 0 ? { divergence: divergences } : {},
16999
+ headline: renderHeadline(graph, errorEvent, locus, rootCause?.node ?? null)
17000
+ };
17001
+ return import_types58.IncidentCardSchema.parse(card);
17002
+ }
17003
+
17004
+ // src/ask.ts
17005
+ init_cjs_shims();
17006
+ var import_types59 = require("@neat.is/types");
16873
17007
  var DEFAULT_MAX_NODES = 3;
16874
17008
  var MAX_FACTS_PER_SECTION = 6;
16875
17009
  var INTENT_RULES = [
@@ -17097,7 +17231,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
17097
17231
  };
17098
17232
  graph.forEachNode((id, attrs) => {
17099
17233
  const node = attrs;
17100
- if (node.type === import_types58.NodeType.FrontierNode) return;
17234
+ if (node.type === import_types59.NodeType.FrontierNode) return;
17101
17235
  const name = nodeName(node);
17102
17236
  const body = idBody(id);
17103
17237
  const labelTokens = /* @__PURE__ */ new Set([...tokens(body), ...tokens(name)]);
@@ -17116,7 +17250,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
17116
17250
  const res = await searchIndex.search(question, 10);
17117
17251
  if (res.provider !== "substring") {
17118
17252
  for (const m of res.matches) {
17119
- if (m.node.type === import_types58.NodeType.FrontierNode) continue;
17253
+ if (m.node.type === import_types59.NodeType.FrontierNode) continue;
17120
17254
  const already = best.get(m.node.id);
17121
17255
  if (!already && m.score < EMBED_MIN_SCORE) continue;
17122
17256
  consider({
@@ -17154,7 +17288,7 @@ function edgeSignalNote(e) {
17154
17288
  function buildRootCauseSection(graph, node, incidents, now) {
17155
17289
  const result = getRootCause(graph, node, void 0, incidents, { now });
17156
17290
  if (!result) return null;
17157
- const lastProv = result.edgeProvenances[result.edgeProvenances.length - 1] ?? import_types58.Provenance.OBSERVED;
17291
+ const lastProv = result.edgeProvenances[result.edgeProvenances.length - 1] ?? import_types59.Provenance.OBSERVED;
17158
17292
  const facts = [
17159
17293
  {
17160
17294
  text: `Root cause: ${result.rootCauseNode} \u2014 ${result.rootCauseReason}`,
@@ -17204,7 +17338,7 @@ function buildObservedSection(graph, node) {
17204
17338
  if (result.observed && result.inboundObservedCount > 0) {
17205
17339
  facts.push({
17206
17340
  text: `no outbound runtime calls, but OTel observed ${result.inboundObservedCount} inbound call path${result.inboundObservedCount === 1 ? "" : "s"} \u2014 a pure receiver`,
17207
- provenance: import_types58.Provenance.OBSERVED
17341
+ provenance: import_types59.Provenance.OBSERVED
17208
17342
  });
17209
17343
  } else {
17210
17344
  return null;
@@ -17232,7 +17366,7 @@ function buildIncidentsSection(node, incidents) {
17232
17366
  const facts = ordered.map((ev) => ({
17233
17367
  text: `${ev.timestamp} \u2014 ${ev.service}: ${ev.errorMessage}`,
17234
17368
  // ErrorEvents are observation records — OBSERVED by definition.
17235
- provenance: import_types58.Provenance.OBSERVED
17369
+ provenance: import_types59.Provenance.OBSERVED
17236
17370
  }));
17237
17371
  return { heading: `Recent incidents (OBSERVED) \u2014 ${relevant.length} recorded`, facts };
17238
17372
  }
@@ -17292,7 +17426,7 @@ function buildGlobalIncidentsSection(incidents) {
17292
17426
  }
17293
17427
  const byKey = /* @__PURE__ */ new Map();
17294
17428
  for (const ev of incidents) {
17295
- const key = ev.affectedNode || (0, import_types58.serviceId)(ev.service);
17429
+ const key = ev.affectedNode || (0, import_types59.serviceId)(ev.service);
17296
17430
  const cur = byKey.get(key);
17297
17431
  if (!cur) {
17298
17432
  byKey.set(key, { key, count: 1, latest: ev.timestamp, sampleMsg: ev.errorMessage });
@@ -17307,7 +17441,7 @@ function buildGlobalIncidentsSection(incidents) {
17307
17441
  const rows = [...byKey.values()].sort((a, b) => b.count - a.count || b.latest.localeCompare(a.latest) || a.key.localeCompare(b.key)).slice(0, MAX_FACTS_PER_SECTION);
17308
17442
  const facts = rows.map((r) => ({
17309
17443
  text: `${r.key} \u2014 ${r.count} incident${r.count === 1 ? "" : "s"}, latest ${r.latest}: ${r.sampleMsg}`,
17310
- provenance: import_types58.Provenance.OBSERVED
17444
+ provenance: import_types59.Provenance.OBSERVED
17311
17445
  }));
17312
17446
  return {
17313
17447
  heading: `Incidents across the system \u2014 ${incidents.length} recorded`,
@@ -17320,7 +17454,7 @@ function buildOverviewSections(graph, incidents) {
17320
17454
  graph.forEachNode((_id, attrs) => {
17321
17455
  const node = attrs;
17322
17456
  nodeByType.set(node.type, (nodeByType.get(node.type) ?? 0) + 1);
17323
- if (node.type === import_types58.NodeType.ServiceNode) services.push(node.id);
17457
+ if (node.type === import_types59.NodeType.ServiceNode) services.push(node.id);
17324
17458
  });
17325
17459
  const edgeByProv = /* @__PURE__ */ new Map();
17326
17460
  graph.forEachEdge((_id, attrs) => {
@@ -17332,10 +17466,10 @@ function buildOverviewSections(graph, incidents) {
17332
17466
  const shapeFacts = [
17333
17467
  { text: `${graph.order} nodes, ${graph.size} edges` },
17334
17468
  {
17335
- text: `${count(import_types58.NodeType.ServiceNode)} services, ${count(import_types58.NodeType.FileNode)} files, ${count(import_types58.NodeType.SymbolNode)} symbols, ${count(import_types58.NodeType.DatabaseNode)} databases`
17469
+ text: `${count(import_types59.NodeType.ServiceNode)} services, ${count(import_types59.NodeType.FileNode)} files, ${count(import_types59.NodeType.SymbolNode)} symbols, ${count(import_types59.NodeType.DatabaseNode)} databases`
17336
17470
  }
17337
17471
  ];
17338
- for (const p of [import_types58.Provenance.EXTRACTED, import_types58.Provenance.OBSERVED, import_types58.Provenance.INFERRED, import_types58.Provenance.STALE]) {
17472
+ for (const p of [import_types59.Provenance.EXTRACTED, import_types59.Provenance.OBSERVED, import_types59.Provenance.INFERRED, import_types59.Provenance.STALE]) {
17339
17473
  const n = edgeByProv.get(p) ?? 0;
17340
17474
  if (n > 0) shapeFacts.push({ text: `${n} ${p} edge${n === 1 ? "" : "s"}`, provenance: p });
17341
17475
  }
@@ -17352,7 +17486,7 @@ function buildOverviewSections(graph, incidents) {
17352
17486
  if (incidents && incidents.length > 0) {
17353
17487
  const incCount = /* @__PURE__ */ new Map();
17354
17488
  for (const ev of incidents) {
17355
- const key = ev.affectedNode || (0, import_types58.serviceId)(ev.service);
17489
+ const key = ev.affectedNode || (0, import_types59.serviceId)(ev.service);
17356
17490
  incCount.set(key, (incCount.get(key) ?? 0) + 1);
17357
17491
  }
17358
17492
  const top = [...incCount.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, MAX_FACTS_PER_SECTION);
@@ -17360,7 +17494,7 @@ function buildOverviewSections(graph, incidents) {
17360
17494
  heading: `Nodes with incidents \u2014 ${incidents.length} recorded`,
17361
17495
  facts: top.map(([k, n]) => ({
17362
17496
  text: `${k} \u2014 ${n} incident${n === 1 ? "" : "s"}`,
17363
- provenance: import_types58.Provenance.OBSERVED
17497
+ provenance: import_types59.Provenance.OBSERVED
17364
17498
  }))
17365
17499
  });
17366
17500
  }
@@ -17496,7 +17630,7 @@ async function askGraph(graph, question, opts = {}) {
17496
17630
  const provSet = /* @__PURE__ */ new Set();
17497
17631
  for (const s of sections) for (const f of s.facts) if (f.provenance) provSet.add(f.provenance);
17498
17632
  const confidence = sections[0]?.facts[0]?.confidence;
17499
- return import_types58.AskResultSchema.parse({
17633
+ return import_types59.AskResultSchema.parse({
17500
17634
  question,
17501
17635
  intent,
17502
17636
  matched,
@@ -17590,7 +17724,7 @@ function canonicalJson(value) {
17590
17724
  init_cjs_shims();
17591
17725
  var import_node_fs36 = require("fs");
17592
17726
  var import_node_path70 = __toESM(require("path"), 1);
17593
- var import_types59 = require("@neat.is/types");
17727
+ var import_types60 = require("@neat.is/types");
17594
17728
  var SCHEMA_VERSION = 7;
17595
17729
  function migrateV1ToV2(payload) {
17596
17730
  const nodes = payload.graph.nodes;
@@ -17614,7 +17748,7 @@ function migrateV5ToV6(payload) {
17614
17748
  if (Array.isArray(nodes)) {
17615
17749
  for (const node of nodes) {
17616
17750
  const attrs = node.attributes;
17617
- if (!attrs || attrs.type !== import_types59.NodeType.InfraNode) continue;
17751
+ if (!attrs || attrs.type !== import_types60.NodeType.InfraNode) continue;
17618
17752
  if (attrs.kind !== "sql-table" && attrs.kind !== "supabase-table") continue;
17619
17753
  if (!Array.isArray(attrs.columns)) attrs.columns = [];
17620
17754
  }
@@ -17630,12 +17764,12 @@ function migrateV2ToV3(payload) {
17630
17764
  for (const edge of edges) {
17631
17765
  const attrs = edge.attributes;
17632
17766
  if (!attrs || attrs.provenance !== "FRONTIER") continue;
17633
- attrs.provenance = import_types59.Provenance.OBSERVED;
17767
+ attrs.provenance = import_types60.Provenance.OBSERVED;
17634
17768
  const type = typeof attrs.type === "string" ? attrs.type : void 0;
17635
17769
  const source = typeof attrs.source === "string" ? attrs.source : void 0;
17636
17770
  const target = typeof attrs.target === "string" ? attrs.target : void 0;
17637
17771
  if (type && source && target) {
17638
- const newId = (0, import_types59.observedEdgeId)(source, target, type);
17772
+ const newId = (0, import_types60.observedEdgeId)(source, target, type);
17639
17773
  attrs.id = newId;
17640
17774
  if (edge.key) edge.key = newId;
17641
17775
  }
@@ -17793,7 +17927,7 @@ init_cjs_shims();
17793
17927
  var import_node_fs37 = require("fs");
17794
17928
  var import_node_os3 = __toESM(require("os"), 1);
17795
17929
  var import_node_path72 = __toESM(require("path"), 1);
17796
- var import_types60 = require("@neat.is/types");
17930
+ var import_types61 = require("@neat.is/types");
17797
17931
  function neatHome() {
17798
17932
  const override = process.env.NEAT_HOME;
17799
17933
  if (override && override.length > 0) return import_node_path72.default.resolve(override);
@@ -17883,7 +18017,7 @@ async function readRegistry() {
17883
18017
  throw err;
17884
18018
  }
17885
18019
  const parsed = JSON.parse(raw);
17886
- return import_types60.RegistryFileSchema.parse(parsed);
18020
+ return import_types61.RegistryFileSchema.parse(parsed);
17887
18021
  }
17888
18022
  async function getProject(name) {
17889
18023
  const reg = await readRegistry();
@@ -18164,15 +18298,15 @@ function getConnectorStatus(id, now = Date.now(), thresholdMs = CONNECTOR_STALE_
18164
18298
 
18165
18299
  // src/connectors/index.ts
18166
18300
  init_cjs_shims();
18167
- var import_types61 = require("@neat.is/types");
18301
+ var import_types62 = require("@neat.is/types");
18168
18302
  var NO_ENV = "unknown";
18169
18303
  function staticCallSiteFor(graph, serviceName, targetNodeId) {
18170
18304
  if (!graph.hasNode(targetNodeId)) return void 0;
18171
18305
  const sites = [];
18172
18306
  for (const edgeId of graph.inboundEdges(targetNodeId)) {
18173
18307
  const edge = graph.getEdgeAttributes(edgeId);
18174
- if (edge.provenance !== import_types61.Provenance.EXTRACTED) continue;
18175
- const parsed = (0, import_types61.parseFileId)(edge.source);
18308
+ if (edge.provenance !== import_types62.Provenance.EXTRACTED) continue;
18309
+ const parsed = (0, import_types62.parseFileId)(edge.source);
18176
18310
  if (!parsed || parsed.service !== serviceName || !edge.evidence) continue;
18177
18311
  const site = { relPath: edge.evidence.file };
18178
18312
  if (edge.evidence.line !== void 0) site.line = edge.evidence.line;
@@ -18183,7 +18317,7 @@ function staticCallSiteFor(graph, serviceName, targetNodeId) {
18183
18317
  function routeCallSiteFor(graph, targetNodeId) {
18184
18318
  if (!graph.hasNode(targetNodeId)) return void 0;
18185
18319
  const attrs = graph.getNodeAttributes(targetNodeId);
18186
- if (attrs.type !== import_types61.NodeType.RouteNode || !attrs.path) return void 0;
18320
+ if (attrs.type !== import_types62.NodeType.RouteNode || !attrs.path) return void 0;
18187
18321
  const site = { relPath: attrs.path };
18188
18322
  if (attrs.line !== void 0) site.line = attrs.line;
18189
18323
  return site;
@@ -18213,7 +18347,7 @@ async function runConnectorPoll(connector, ctx, graph, resolveTarget) {
18213
18347
  errorMessage: signal.incident.errorMessage,
18214
18348
  ...signal.incident.attributes ? { attributes: signal.incident.attributes } : {},
18215
18349
  affectedNode: resolved.targetNodeId
18216
- });
18350
+ }, ctx.project);
18217
18351
  continue;
18218
18352
  }
18219
18353
  if (resolved.ensureInfraNode) {
@@ -18754,23 +18888,23 @@ async function fetchPgStatStatements(connectionString, limit = DEFAULT_STATEMENT
18754
18888
 
18755
18889
  // src/connectors/supabase/resolve.ts
18756
18890
  init_cjs_shims();
18757
- var import_types63 = require("@neat.is/types");
18891
+ var import_types64 = require("@neat.is/types");
18758
18892
  function createSupabaseResolveTarget(graph, config) {
18759
18893
  return (signal, _ctx) => {
18760
18894
  if (signal.targetKind !== SUPABASE_TABLE_TARGET_KIND && signal.targetKind !== SUPABASE_RPC_TARGET_KIND) {
18761
18895
  return null;
18762
18896
  }
18763
- const subResourceId = (0, import_types63.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
18897
+ const subResourceId = (0, import_types64.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
18764
18898
  if (graph.hasNode(subResourceId)) {
18765
- return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types63.EdgeType.CALLS };
18899
+ return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types64.EdgeType.CALLS };
18766
18900
  }
18767
- const bareResourceId = (0, import_types63.infraId)(signal.targetKind, signal.targetName);
18901
+ const bareResourceId = (0, import_types64.infraId)(signal.targetKind, signal.targetName);
18768
18902
  if (graph.hasNode(bareResourceId)) {
18769
- return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types63.EdgeType.CALLS };
18903
+ return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types64.EdgeType.CALLS };
18770
18904
  }
18771
- const projectLevelId = (0, import_types63.infraId)("supabase", config.nodeRef);
18905
+ const projectLevelId = (0, import_types64.infraId)("supabase", config.nodeRef);
18772
18906
  if (graph.hasNode(projectLevelId)) {
18773
- return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types63.EdgeType.CALLS };
18907
+ return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types64.EdgeType.CALLS };
18774
18908
  }
18775
18909
  return null;
18776
18910
  };
@@ -18863,7 +18997,7 @@ function createSupabaseConnector(graph, config, deps = {}) {
18863
18997
 
18864
18998
  // src/connectors/railway/index.ts
18865
18999
  init_cjs_shims();
18866
- var import_types67 = require("@neat.is/types");
19000
+ var import_types68 = require("@neat.is/types");
18867
19001
 
18868
19002
  // src/connectors/railway/client.ts
18869
19003
  init_cjs_shims();
@@ -19014,7 +19148,7 @@ function buildRailwayRouteIndex(graph, serviceName) {
19014
19148
  const out = [];
19015
19149
  graph.forEachNode((_id, attrs) => {
19016
19150
  const node = attrs;
19017
- if (node.type !== import_types67.NodeType.RouteNode) return;
19151
+ if (node.type !== import_types68.NodeType.RouteNode) return;
19018
19152
  const route = attrs;
19019
19153
  if (route.service !== serviceName) return;
19020
19154
  out.push({
@@ -19118,12 +19252,12 @@ function createRailwayResolveTarget(config) {
19118
19252
  const serviceName = config.serviceNameById[config.serviceId];
19119
19253
  if (!serviceName) return null;
19120
19254
  if (signal.targetKind === ROUTE_TARGET_KIND) {
19121
- return { targetNodeId: signal.targetName, serviceName, edgeType: import_types67.EdgeType.CALLS };
19255
+ return { targetNodeId: signal.targetName, serviceName, edgeType: import_types68.EdgeType.CALLS };
19122
19256
  }
19123
19257
  if (signal.targetKind === PEER_SERVICE_TARGET_KIND) {
19124
19258
  const peerName = config.serviceNameById[signal.targetName];
19125
19259
  if (!peerName) return null;
19126
- return { targetNodeId: (0, import_types67.serviceId)(peerName), serviceName, edgeType: import_types67.EdgeType.CONNECTS_TO };
19260
+ return { targetNodeId: (0, import_types68.serviceId)(peerName), serviceName, edgeType: import_types68.EdgeType.CONNECTS_TO };
19127
19261
  }
19128
19262
  return null;
19129
19263
  };
@@ -19311,7 +19445,7 @@ function mapLogEntriesToSignals(entries) {
19311
19445
 
19312
19446
  // src/connectors/firebase/resolve.ts
19313
19447
  init_cjs_shims();
19314
- var import_types68 = require("@neat.is/types");
19448
+ var import_types69 = require("@neat.is/types");
19315
19449
  function neatServiceNameFor(resourceType, resourceName, serviceMap) {
19316
19450
  switch (resourceType) {
19317
19451
  case "cloud_function":
@@ -19326,7 +19460,7 @@ function routeEntriesFor(graph, serviceName) {
19326
19460
  const entries = [];
19327
19461
  graph.forEachNode((_id, attrs) => {
19328
19462
  const node = attrs;
19329
- if (node.type !== import_types68.NodeType.RouteNode) return;
19463
+ if (node.type !== import_types69.NodeType.RouteNode) return;
19330
19464
  const route = attrs;
19331
19465
  if (route.service !== serviceName) return;
19332
19466
  entries.push({
@@ -19358,7 +19492,7 @@ function createFirebaseResolveTarget(graph, serviceMap) {
19358
19492
  return {
19359
19493
  targetNodeId: match.routeNodeId,
19360
19494
  serviceName,
19361
- edgeType: import_types68.EdgeType.CALLS
19495
+ edgeType: import_types69.EdgeType.CALLS
19362
19496
  };
19363
19497
  };
19364
19498
  }
@@ -19385,7 +19519,7 @@ init_cjs_shims();
19385
19519
 
19386
19520
  // src/connectors/cloudflare/connector.ts
19387
19521
  init_cjs_shims();
19388
- var import_types70 = require("@neat.is/types");
19522
+ var import_types71 = require("@neat.is/types");
19389
19523
 
19390
19524
  // src/connectors/cloudflare/client.ts
19391
19525
  init_cjs_shims();
@@ -19549,7 +19683,7 @@ function findTaggedWorkerFileNode(graph, workerName) {
19549
19683
  graph.forEachNode((id, attrs) => {
19550
19684
  if (found) return;
19551
19685
  const a = attrs;
19552
- if (a.type === import_types70.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
19686
+ if (a.type === import_types71.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
19553
19687
  found = id;
19554
19688
  }
19555
19689
  });
@@ -19561,7 +19695,7 @@ function findMatchingRouteNode(graph, serviceName, method, path76) {
19561
19695
  graph.forEachNode((id, attrs) => {
19562
19696
  if (found) return;
19563
19697
  const a = attrs;
19564
- if (a.type !== import_types70.NodeType.RouteNode || a.service !== serviceName) return;
19698
+ if (a.type !== import_types71.NodeType.RouteNode || a.service !== serviceName) return;
19565
19699
  if (!a.pathTemplate || normalizePathTemplate(a.pathTemplate) !== normalizedPath) return;
19566
19700
  const routeMethod = (a.method ?? "").toUpperCase();
19567
19701
  if (routeMethod !== "ALL" && routeMethod !== method) return;
@@ -19580,11 +19714,11 @@ function createCloudflareResolveTarget(config, graph) {
19580
19714
  };
19581
19715
  const mapping = config.workers?.[scriptName];
19582
19716
  if (mapping) {
19583
- const wholeFileId = (0, import_types70.fileId)(mapping.service, mapping.entryFile);
19717
+ const wholeFileId = (0, import_types71.fileId)(mapping.service, mapping.entryFile);
19584
19718
  return {
19585
19719
  targetNodeId: resolveRouteGrain(mapping.service, wholeFileId),
19586
19720
  serviceName: mapping.service,
19587
- edgeType: import_types70.EdgeType.CALLS
19721
+ edgeType: import_types71.EdgeType.CALLS
19588
19722
  };
19589
19723
  }
19590
19724
  const taggedFileId = findTaggedWorkerFileNode(graph, scriptName);
@@ -19593,13 +19727,13 @@ function createCloudflareResolveTarget(config, graph) {
19593
19727
  return {
19594
19728
  targetNodeId: resolveRouteGrain(fileNode.service, taggedFileId),
19595
19729
  serviceName: fileNode.service,
19596
- edgeType: import_types70.EdgeType.CALLS
19730
+ edgeType: import_types71.EdgeType.CALLS
19597
19731
  };
19598
19732
  }
19599
19733
  return {
19600
- targetNodeId: (0, import_types70.infraId)("cloudflare-worker", scriptName),
19734
+ targetNodeId: (0, import_types71.infraId)("cloudflare-worker", scriptName),
19601
19735
  serviceName: scriptName,
19602
- edgeType: import_types70.EdgeType.CALLS,
19736
+ edgeType: import_types71.EdgeType.CALLS,
19603
19737
  ensureInfraNode: { kind: "cloudflare-worker", name: scriptName, provider: "cloudflare" }
19604
19738
  };
19605
19739
  };
@@ -19795,14 +19929,14 @@ function diffNeonStatementsToSignals(rows, previous, observedAtIso) {
19795
19929
 
19796
19930
  // src/connectors/neon/resolve.ts
19797
19931
  init_cjs_shims();
19798
- var import_types74 = require("@neat.is/types");
19932
+ var import_types75 = require("@neat.is/types");
19799
19933
  function createNeonResolveTarget(config) {
19800
19934
  return (signal) => {
19801
19935
  if (signal.targetKind !== NEON_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
19802
19936
  return {
19803
- targetNodeId: (0, import_types74.infraId)("sql-table", signal.targetName),
19937
+ targetNodeId: (0, import_types75.infraId)("sql-table", signal.targetName),
19804
19938
  serviceName: config.serviceName,
19805
- edgeType: import_types74.EdgeType.CALLS,
19939
+ edgeType: import_types75.EdgeType.CALLS,
19806
19940
  ensureInfraNode: { kind: "sql-table", name: signal.targetName, provider: "neon" }
19807
19941
  };
19808
19942
  };
@@ -19983,14 +20117,14 @@ function mapLogEntriesToSignals2(entries) {
19983
20117
 
19984
20118
  // src/connectors/cloud-run/resolve.ts
19985
20119
  init_cjs_shims();
19986
- var import_types78 = require("@neat.is/types");
20120
+ var import_types79 = require("@neat.is/types");
19987
20121
  var CLOUD_RUN_SERVICE_INFRA_KIND = "cloud-run-service";
19988
20122
  function findMatchingRouteNode2(graph, serviceName, method, normalizedPath) {
19989
20123
  let found = null;
19990
20124
  graph.forEachNode((_id, attrs) => {
19991
20125
  if (found) return;
19992
20126
  const node = attrs;
19993
- if (node.type !== import_types78.NodeType.RouteNode) return;
20127
+ if (node.type !== import_types79.NodeType.RouteNode) return;
19994
20128
  const route = attrs;
19995
20129
  if (route.service !== serviceName || !route.pathTemplate) return;
19996
20130
  if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
@@ -20015,13 +20149,13 @@ function createCloudRunResolveTarget(graph, config) {
20015
20149
  normalizePathTemplate(path76)
20016
20150
  );
20017
20151
  if (routeNodeId) {
20018
- return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types78.EdgeType.CALLS };
20152
+ return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types79.EdgeType.CALLS };
20019
20153
  }
20020
20154
  }
20021
20155
  return {
20022
- targetNodeId: (0, import_types78.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
20156
+ targetNodeId: (0, import_types79.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
20023
20157
  serviceName: mappedService ?? gcpServiceName,
20024
- edgeType: import_types78.EdgeType.CALLS,
20158
+ edgeType: import_types79.EdgeType.CALLS,
20025
20159
  ensureInfraNode: {
20026
20160
  kind: CLOUD_RUN_SERVICE_INFRA_KIND,
20027
20161
  name: gcpServiceName,
@@ -20203,14 +20337,14 @@ function mapLogEntriesToSignals3(entries) {
20203
20337
 
20204
20338
  // src/connectors/gcp-lb/resolve.ts
20205
20339
  init_cjs_shims();
20206
- var import_types82 = require("@neat.is/types");
20340
+ var import_types83 = require("@neat.is/types");
20207
20341
  var GCP_LB_BACKEND_INFRA_KIND = "gcp-lb-backend";
20208
20342
  function findMatchingRouteNode3(graph, serviceName, method, normalizedPath) {
20209
20343
  let found = null;
20210
20344
  graph.forEachNode((_id, attrs) => {
20211
20345
  if (found) return;
20212
20346
  const node = attrs;
20213
- if (node.type !== import_types82.NodeType.RouteNode) return;
20347
+ if (node.type !== import_types83.NodeType.RouteNode) return;
20214
20348
  const route = attrs;
20215
20349
  if (route.service !== serviceName || !route.pathTemplate) return;
20216
20350
  if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
@@ -20235,13 +20369,13 @@ function createGcpLbResolveTarget(graph, config) {
20235
20369
  normalizePathTemplate(path76)
20236
20370
  );
20237
20371
  if (routeNodeId) {
20238
- return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types82.EdgeType.CALLS };
20372
+ return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types83.EdgeType.CALLS };
20239
20373
  }
20240
20374
  }
20241
20375
  return {
20242
- targetNodeId: (0, import_types82.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
20376
+ targetNodeId: (0, import_types83.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
20243
20377
  serviceName: mappedService ?? backendServiceName,
20244
- edgeType: import_types82.EdgeType.CALLS,
20378
+ edgeType: import_types83.EdgeType.CALLS,
20245
20379
  ensureInfraNode: {
20246
20380
  kind: GCP_LB_BACKEND_INFRA_KIND,
20247
20381
  name: backendServiceName,
@@ -20282,7 +20416,7 @@ function createGcpLbConnector(graph, config = {}) {
20282
20416
 
20283
20417
  // src/connectors/render/index.ts
20284
20418
  init_cjs_shims();
20285
- var import_types85 = require("@neat.is/types");
20419
+ var import_types86 = require("@neat.is/types");
20286
20420
 
20287
20421
  // src/connectors/render/types.ts
20288
20422
  init_cjs_shims();
@@ -20360,7 +20494,7 @@ function buildRenderRouteIndex(graph, serviceName) {
20360
20494
  const out = [];
20361
20495
  graph.forEachNode((_id, attrs) => {
20362
20496
  const node = attrs;
20363
- if (node.type !== import_types85.NodeType.RouteNode) return;
20497
+ if (node.type !== import_types86.NodeType.RouteNode) return;
20364
20498
  const route = attrs;
20365
20499
  if (route.service !== serviceName) return;
20366
20500
  out.push({
@@ -20445,7 +20579,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
20445
20579
  function createRenderResolveTarget(config) {
20446
20580
  return (signal) => {
20447
20581
  if (signal.targetKind === ROUTE_TARGET_KIND2) {
20448
- return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types85.EdgeType.CALLS };
20582
+ return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types86.EdgeType.CALLS };
20449
20583
  }
20450
20584
  return null;
20451
20585
  };
@@ -20583,21 +20717,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
20583
20717
 
20584
20718
  // src/connectors/planetscale/resolve.ts
20585
20719
  init_cjs_shims();
20586
- var import_types89 = require("@neat.is/types");
20720
+ var import_types90 = require("@neat.is/types");
20587
20721
  var PLANETSCALE_DATABASE_KIND = "planetscale-database";
20588
20722
  function createPlanetscaleResolveTarget(graph, config) {
20589
20723
  const databaseName = `${config.organization}/${config.database}`;
20590
20724
  return (signal, _ctx) => {
20591
20725
  if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
20592
- const tableId = (0, import_types89.infraId)("sql-table", signal.targetName);
20726
+ const tableId = (0, import_types90.infraId)("sql-table", signal.targetName);
20593
20727
  if (graph.hasNode(tableId)) {
20594
- return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types89.EdgeType.CALLS };
20728
+ return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types90.EdgeType.CALLS };
20595
20729
  }
20596
- const providerId = (0, import_types89.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
20730
+ const providerId = (0, import_types90.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
20597
20731
  return {
20598
20732
  targetNodeId: providerId,
20599
20733
  serviceName: config.serviceName,
20600
- edgeType: import_types89.EdgeType.CALLS,
20734
+ edgeType: import_types90.EdgeType.CALLS,
20601
20735
  ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
20602
20736
  };
20603
20737
  };
@@ -20862,7 +20996,7 @@ function mapBuildsToSignals(builds, serviceName) {
20862
20996
 
20863
20997
  // src/connectors/eas/resolve.ts
20864
20998
  init_cjs_shims();
20865
- var import_types94 = require("@neat.is/types");
20999
+ var import_types95 = require("@neat.is/types");
20866
21000
  var NO_ENV2 = "unknown";
20867
21001
  var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
20868
21002
  var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
@@ -20878,8 +21012,8 @@ function configBasenamesForPhase(phase) {
20878
21012
  function configNodeService(graph, configNodeId) {
20879
21013
  for (const edgeId of graph.inboundEdges(configNodeId)) {
20880
21014
  const edge = graph.getEdgeAttributes(edgeId);
20881
- if (edge.type !== import_types94.EdgeType.CONFIGURED_BY) continue;
20882
- const parsed = (0, import_types94.parseFileId)(edge.source);
21015
+ if (edge.type !== import_types95.EdgeType.CONFIGURED_BY) continue;
21016
+ const parsed = (0, import_types95.parseFileId)(edge.source);
20883
21017
  if (parsed) return parsed.service;
20884
21018
  }
20885
21019
  return null;
@@ -20890,7 +21024,7 @@ function findConfigNode(graph, basenames, serviceName) {
20890
21024
  graph.forEachNode((id, attrs) => {
20891
21025
  if (scoped) return;
20892
21026
  const node = attrs;
20893
- if (node.type !== import_types94.NodeType.ConfigNode) return;
21027
+ if (node.type !== import_types95.NodeType.ConfigNode) return;
20894
21028
  if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
20895
21029
  if (anyMatch === null) anyMatch = id;
20896
21030
  if (configNodeService(graph, id) === serviceName) scoped = id;
@@ -20907,13 +21041,13 @@ function createEasResolveTarget(graph) {
20907
21041
  if (basenames.length > 0) {
20908
21042
  const configNodeId = findConfigNode(graph, basenames, serviceName);
20909
21043
  if (configNodeId) {
20910
- return { targetNodeId: configNodeId, serviceName, edgeType: import_types94.EdgeType.CALLS };
21044
+ return { targetNodeId: configNodeId, serviceName, edgeType: import_types95.EdgeType.CALLS };
20911
21045
  }
20912
21046
  }
20913
21047
  return {
20914
21048
  targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV2),
20915
21049
  serviceName,
20916
- edgeType: import_types94.EdgeType.CALLS
21050
+ edgeType: import_types95.EdgeType.CALLS
20917
21051
  };
20918
21052
  };
20919
21053
  }
@@ -21628,11 +21762,11 @@ function registerRoutes(scope, ctx) {
21628
21762
  const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
21629
21763
  const parsed = [];
21630
21764
  for (const c of candidates) {
21631
- const r = import_types97.DivergenceTypeSchema.safeParse(c);
21765
+ const r = import_types98.DivergenceTypeSchema.safeParse(c);
21632
21766
  if (!r.success) {
21633
21767
  return reply.code(400).send({
21634
21768
  error: `unknown divergence type "${c}"`,
21635
- allowed: import_types97.DivergenceTypeSchema.options
21769
+ allowed: import_types98.DivergenceTypeSchema.options
21636
21770
  });
21637
21771
  }
21638
21772
  parsed.push(r.data);
@@ -21749,6 +21883,7 @@ function registerRoutes(scope, ctx) {
21749
21883
  reg.connector,
21750
21884
  {
21751
21885
  projectDir: proj.scanPath ?? "",
21886
+ project: proj.name,
21752
21887
  credentials: reg.credentials,
21753
21888
  ...incidentsPath ? { errorsPath: incidentsPath } : {}
21754
21889
  },
@@ -21812,6 +21947,39 @@ function registerRoutes(scope, ctx) {
21812
21947
  if (!result) return reply.code(404).send({ error: "no root cause found", id: nodeId });
21813
21948
  return result;
21814
21949
  });
21950
+ scope.get("/graph/incident-card/:nodeId", async (req, reply) => {
21951
+ const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
21952
+ if (!proj) return;
21953
+ const { nodeId } = req.params;
21954
+ if (!proj.graph.hasNode(nodeId)) {
21955
+ return reply.code(404).send({ error: "node not found", id: nodeId });
21956
+ }
21957
+ const epath = errorsPathFor(proj);
21958
+ const incidents = epath ? await readErrorEvents(epath) : [];
21959
+ let errorEvent;
21960
+ if (req.query.errorId) {
21961
+ errorEvent = incidents.find((e) => e.id === req.query.errorId);
21962
+ if (!errorEvent) {
21963
+ return reply.code(404).send({ error: "error event not found", id: req.query.errorId });
21964
+ }
21965
+ } else {
21966
+ const svc = nodeId.replace(/^service:/, "");
21967
+ errorEvent = [...incidents].filter((e) => e.affectedNode === nodeId || e.service === svc).sort((a, b) => (b.timestamp ?? "").localeCompare(a.timestamp ?? ""))[0];
21968
+ if (!errorEvent) {
21969
+ return reply.code(404).send({ error: "no incident found for node", id: nodeId });
21970
+ }
21971
+ }
21972
+ const policyPath = ctx.policyFilePathFor(proj);
21973
+ let policies = [];
21974
+ if (policyPath) {
21975
+ try {
21976
+ policies = await loadPolicyFile(policyPath);
21977
+ } catch {
21978
+ policies = [];
21979
+ }
21980
+ }
21981
+ return buildIncidentCard(proj.graph, errorEvent, incidents, policies);
21982
+ });
21815
21983
  scope.get("/graph/blast-radius/:nodeId", async (req, reply) => {
21816
21984
  const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
21817
21985
  if (!proj) return;
@@ -21994,7 +22162,7 @@ function registerRoutes(scope, ctx) {
21994
22162
  const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
21995
22163
  let violations = await log.readAll();
21996
22164
  if (req.query.severity) {
21997
- const sev = import_types97.PolicySeveritySchema.safeParse(req.query.severity);
22165
+ const sev = import_types98.PolicySeveritySchema.safeParse(req.query.severity);
21998
22166
  if (!sev.success) {
21999
22167
  return reply.code(400).send({
22000
22168
  error: "invalid severity",
@@ -22033,7 +22201,7 @@ function registerRoutes(scope, ctx) {
22033
22201
  scope.post("/policies/check", async (req, reply) => {
22034
22202
  const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
22035
22203
  if (!proj) return;
22036
- const parsed = import_types97.PoliciesCheckBodySchema.safeParse(req.body ?? {});
22204
+ const parsed = import_types98.PoliciesCheckBodySchema.safeParse(req.body ?? {});
22037
22205
  if (!parsed.success) {
22038
22206
  return reply.code(400).send({
22039
22207
  error: "invalid /policies/check body",