@neat.is/core 0.9.11 → 0.9.12

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
@@ -59,8 +59,8 @@ function mountBearerAuth(app, opts) {
59
59
  ]);
60
60
  const publicRead = opts.publicRead === true;
61
61
  app.addHook("preHandler", (req, reply, done) => {
62
- const path76 = (req.url.split("?")[0] ?? "").replace(/\/+$/, "");
63
- if (exactUnauthPaths.has(path76) || PROJECT_SCOPED_UNAUTH_PATTERN.test(path76)) {
62
+ const path77 = (req.url.split("?")[0] ?? "").replace(/\/+$/, "");
63
+ if (exactUnauthPaths.has(path77) || PROJECT_SCOPED_UNAUTH_PATTERN.test(path77)) {
64
64
  done();
65
65
  return;
66
66
  }
@@ -192,8 +192,8 @@ function reshapeGrpcRequest(req) {
192
192
  };
193
193
  }
194
194
  function resolveProtoRoot() {
195
- const here = import_node_path54.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
196
- return import_node_path54.default.resolve(here, "..", "proto");
195
+ const here = import_node_path55.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
196
+ return import_node_path55.default.resolve(here, "..", "proto");
197
197
  }
198
198
  function loadTraceService() {
199
199
  const protoRoot = resolveProtoRoot();
@@ -261,13 +261,13 @@ async function startOtelGrpcReceiver(opts) {
261
261
  })
262
262
  };
263
263
  }
264
- var import_node_url, import_node_path54, import_node_crypto2, grpc, protoLoader;
264
+ var import_node_url, import_node_path55, import_node_crypto2, grpc, protoLoader;
265
265
  var init_otel_grpc = __esm({
266
266
  "src/otel-grpc.ts"() {
267
267
  "use strict";
268
268
  init_cjs_shims();
269
269
  import_node_url = require("url");
270
- import_node_path54 = __toESM(require("path"), 1);
270
+ import_node_path55 = __toESM(require("path"), 1);
271
271
  import_node_crypto2 = require("crypto");
272
272
  grpc = __toESM(require("@grpc/grpc-js"), 1);
273
273
  protoLoader = __toESM(require("@grpc/proto-loader"), 1);
@@ -413,8 +413,8 @@ function websocketChannelPathOf(attrs) {
413
413
  const v = attrs[key];
414
414
  if (typeof v === "string" && v.length > 0) {
415
415
  const q = v.indexOf("?");
416
- const path76 = q === -1 ? v : v.slice(0, q);
417
- if (path76.length > 0) return path76;
416
+ const path77 = q === -1 ? v : v.slice(0, q);
417
+ if (path77.length > 0) return path77;
418
418
  }
419
419
  }
420
420
  return void 0;
@@ -476,10 +476,10 @@ function parseOtlpRequest(body) {
476
476
  return out;
477
477
  }
478
478
  function loadProtoRoot() {
479
- const here = import_node_path55.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl));
480
- const protoRoot = import_node_path55.default.resolve(here, "..", "proto");
479
+ const here = import_node_path56.default.dirname((0, import_node_url2.fileURLToPath)(importMetaUrl));
480
+ const protoRoot = import_node_path56.default.resolve(here, "..", "proto");
481
481
  const root = new import_protobufjs.default.Root();
482
- root.resolvePath = (_origin, target) => import_node_path55.default.resolve(protoRoot, target);
482
+ root.resolvePath = (_origin, target) => import_node_path56.default.resolve(protoRoot, target);
483
483
  root.loadSync(
484
484
  "opentelemetry/proto/collector/trace/v1/trace_service.proto",
485
485
  { keepCase: true }
@@ -741,12 +741,12 @@ async function buildOtelReceiver(opts) {
741
741
  };
742
742
  return decorated;
743
743
  }
744
- var import_node_path55, import_node_url2, import_node_zlib, import_fastify, import_protobufjs, ENV_ATTR_CANONICAL, ENV_ATTR_COMPAT, ENV_FALLBACK, exportTraceServiceRequestType, exportTraceServiceResponseType, cachedProtobufResponseBody;
744
+ var import_node_path56, import_node_url2, import_node_zlib, import_fastify, import_protobufjs, ENV_ATTR_CANONICAL, ENV_ATTR_COMPAT, ENV_FALLBACK, exportTraceServiceRequestType, exportTraceServiceResponseType, cachedProtobufResponseBody;
745
745
  var init_otel = __esm({
746
746
  "src/otel.ts"() {
747
747
  "use strict";
748
748
  init_cjs_shims();
749
- import_node_path55 = __toESM(require("path"), 1);
749
+ import_node_path56 = __toESM(require("path"), 1);
750
750
  import_node_url2 = require("url");
751
751
  import_node_zlib = __toESM(require("zlib"), 1);
752
752
  import_fastify = __toESM(require("fastify"), 1);
@@ -763,7 +763,7 @@ var init_otel = __esm({
763
763
 
764
764
  // src/server.ts
765
765
  init_cjs_shims();
766
- var import_node_path75 = __toESM(require("path"), 1);
766
+ var import_node_path76 = __toESM(require("path"), 1);
767
767
 
768
768
  // src/graph.ts
769
769
  init_cjs_shims();
@@ -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_types98 = require("@neat.is/types");
790
+ var import_types100 = require("@neat.is/types");
791
791
 
792
792
  // src/extend/index.ts
793
793
  init_cjs_shims();
@@ -899,12 +899,12 @@ var HOOK_WALK_SKIP_DIRS = /* @__PURE__ */ new Set([
899
899
  ]);
900
900
  async function findHookFiles(scanPath) {
901
901
  const found = [];
902
- const walk10 = async (dir) => {
902
+ const walk11 = async (dir) => {
903
903
  const entries = await import_node_fs2.promises.readdir(dir, { withFileTypes: true }).catch(() => []);
904
904
  for (const entry of entries) {
905
905
  if (entry.isDirectory()) {
906
906
  if (entry.name.startsWith(".") || HOOK_WALK_SKIP_DIRS.has(entry.name)) continue;
907
- await walk10(import_node_path2.default.join(dir, entry.name));
907
+ await walk11(import_node_path2.default.join(dir, entry.name));
908
908
  } else if (entry.isFile()) {
909
909
  if ((entry.name.startsWith("instrumentation") || entry.name.startsWith("otel-init")) && /\.(ts|js|cjs|mjs)$/.test(entry.name)) {
910
910
  const rel = import_node_path2.default.relative(scanPath, import_node_path2.default.join(dir, entry.name));
@@ -913,7 +913,7 @@ async function findHookFiles(scanPath) {
913
913
  }
914
914
  }
915
915
  };
916
- await walk10(scanPath);
916
+ await walk11(scanPath);
917
917
  return found.sort();
918
918
  }
919
919
  async function pickPrimaryHookFile(scanPath, hookFiles, snippet2) {
@@ -2320,7 +2320,7 @@ function buildServiceHostIndex(services) {
2320
2320
  async function walkSourceFiles(dir, excludeDirs = []) {
2321
2321
  const excluded = new Set(excludeDirs.map((d) => import_node_path7.default.resolve(d)));
2322
2322
  const out = [];
2323
- async function walk10(current) {
2323
+ async function walk11(current) {
2324
2324
  const entries = await import_node_fs7.promises.readdir(current, { withFileTypes: true }).catch(() => []);
2325
2325
  for (const entry of entries) {
2326
2326
  const full = import_node_path7.default.join(current, entry.name);
@@ -2328,7 +2328,7 @@ async function walkSourceFiles(dir, excludeDirs = []) {
2328
2328
  if (IGNORED_DIRS.has(entry.name)) continue;
2329
2329
  if (excluded.has(import_node_path7.default.resolve(full))) continue;
2330
2330
  if (await isPythonVenvDir(full)) continue;
2331
- await walk10(full);
2331
+ await walk11(full);
2332
2332
  } else if (entry.isFile() && SERVICE_FILE_EXTENSIONS.has(import_node_path7.default.extname(entry.name)) && // Skip NEAT's own generated `otel-init.*` bootstrap — extracting it
2333
2333
  // would attribute our instrumentation imports to the user's service.
2334
2334
  !isNeatAuthoredSourceFile(entry.name)) {
@@ -2336,7 +2336,7 @@ async function walkSourceFiles(dir, excludeDirs = []) {
2336
2336
  }
2337
2337
  }
2338
2338
  }
2339
- await walk10(dir);
2339
+ await walk11(dir);
2340
2340
  return out;
2341
2341
  }
2342
2342
  async function loadSourceFiles(dir, excludeDirs = []) {
@@ -2932,8 +2932,8 @@ function chiRoutesFromSource(source, parser) {
2932
2932
  chiWalk(tree.rootNode, "", out);
2933
2933
  return out;
2934
2934
  }
2935
- function stripChiRegex(path76) {
2936
- return path76.replace(/\{([^{}:]+):[^{}]*\}/g, "{$1}");
2935
+ function stripChiRegex(path77) {
2936
+ return path77.replace(/\{([^{}:]+):[^{}]*\}/g, "{$1}");
2937
2937
  }
2938
2938
  function chiWalk(node, prefix, out) {
2939
2939
  for (let i = 0; i < node.namedChildCount; i++) {
@@ -3605,9 +3605,9 @@ function rubyRocketRoute(args) {
3605
3605
  if (!pair || pair.type !== "pair") continue;
3606
3606
  const k = pair.childForFieldName("key");
3607
3607
  if (k?.type !== "string") continue;
3608
- const path76 = rubyLiteral(k);
3609
- if (path76 === null) continue;
3610
- return { path: path76, target: rubyLiteral(pair.childForFieldName("value")) };
3608
+ const path77 = rubyLiteral(k);
3609
+ if (path77 === null) continue;
3610
+ return { path: path77, target: rubyLiteral(pair.childForFieldName("value")) };
3611
3611
  }
3612
3612
  return null;
3613
3613
  }
@@ -6102,29 +6102,29 @@ function promoteFrontierNodes(graph, opts = {}) {
6102
6102
  toPromote.push({ frontierId: id, serviceId: target });
6103
6103
  });
6104
6104
  let promoted = 0;
6105
- for (const { frontierId: frontierId2, serviceId: serviceId16 } of toPromote) {
6105
+ for (const { frontierId: frontierId2, serviceId: serviceId17 } of toPromote) {
6106
6106
  if (opts.policies && opts.policies.length > 0 && opts.policyCtx) {
6107
6107
  const gate = canPromoteFrontier(graph, frontierId2, opts.policies, opts.policyCtx);
6108
6108
  if (!gate.allowed) {
6109
6109
  continue;
6110
6110
  }
6111
6111
  }
6112
- rewireFrontierEdges(graph, frontierId2, serviceId16);
6112
+ rewireFrontierEdges(graph, frontierId2, serviceId17);
6113
6113
  graph.dropNode(frontierId2);
6114
6114
  promoted++;
6115
6115
  }
6116
6116
  return promoted;
6117
6117
  }
6118
- function rewireFrontierEdges(graph, frontierId2, serviceId16) {
6118
+ function rewireFrontierEdges(graph, frontierId2, serviceId17) {
6119
6119
  const inbound = [...graph.inboundEdges(frontierId2)];
6120
6120
  const outbound = [...graph.outboundEdges(frontierId2)];
6121
6121
  for (const edgeId of inbound) {
6122
6122
  const edge = graph.getEdgeAttributes(edgeId);
6123
- rebuildEdge(graph, edge, edge.source, serviceId16, edgeId);
6123
+ rebuildEdge(graph, edge, edge.source, serviceId17, edgeId);
6124
6124
  }
6125
6125
  for (const edgeId of outbound) {
6126
6126
  const edge = graph.getEdgeAttributes(edgeId);
6127
- rebuildEdge(graph, edge, serviceId16, edge.target, edgeId);
6127
+ rebuildEdge(graph, edge, serviceId17, edge.target, edgeId);
6128
6128
  }
6129
6129
  }
6130
6130
  function rebuildEdge(graph, edge, newSource, newTarget, oldEdgeId) {
@@ -6464,19 +6464,19 @@ function confidenceFromMix(edges, now = Date.now()) {
6464
6464
  function longestIncomingWalk(graph, start, maxDepth) {
6465
6465
  let best = { path: [start], edges: [] };
6466
6466
  const visited = /* @__PURE__ */ new Set([start]);
6467
- function step(node, path76, edges) {
6468
- if (path76.length > best.path.length) {
6469
- best = { path: [...path76], edges: [...edges] };
6467
+ function step(node, path77, edges) {
6468
+ if (path77.length > best.path.length) {
6469
+ best = { path: [...path77], edges: [...edges] };
6470
6470
  }
6471
- if (path76.length - 1 >= maxDepth) return;
6471
+ if (path77.length - 1 >= maxDepth) return;
6472
6472
  const incoming = bestEdgeBySource(graph, graph.inboundEdges(node));
6473
6473
  for (const [srcId, edge] of incoming) {
6474
6474
  if (visited.has(srcId)) continue;
6475
6475
  visited.add(srcId);
6476
- path76.push(srcId);
6476
+ path77.push(srcId);
6477
6477
  edges.push(edge);
6478
- step(srcId, path76, edges);
6479
- path76.pop();
6478
+ step(srcId, path77, edges);
6479
+ path77.pop();
6480
6480
  edges.pop();
6481
6481
  visited.delete(srcId);
6482
6482
  }
@@ -6484,14 +6484,14 @@ function longestIncomingWalk(graph, start, maxDepth) {
6484
6484
  step(start, [start], []);
6485
6485
  return best;
6486
6486
  }
6487
- function databaseRootCauseShape(graph, origin, walk10) {
6487
+ function databaseRootCauseShape(graph, origin, walk11) {
6488
6488
  const targetDb = origin;
6489
6489
  const candidatePairs = compatPairs().filter((p) => p.engine === targetDb.engine);
6490
6490
  if (candidatePairs.length === 0) return null;
6491
- for (const id of walk10.path) {
6491
+ for (const id of walk11.path) {
6492
6492
  const owner = resolveOwningService(graph, id);
6493
6493
  if (!owner) continue;
6494
- const { id: serviceId16, svc } = owner;
6494
+ const { id: serviceId17, svc } = owner;
6495
6495
  const deps = svc.dependencies ?? {};
6496
6496
  for (const pair of candidatePairs) {
6497
6497
  const declared = deps[pair.driver];
@@ -6504,7 +6504,7 @@ function databaseRootCauseShape(graph, origin, walk10) {
6504
6504
  );
6505
6505
  if (!result.compatible) {
6506
6506
  return {
6507
- rootCauseNode: serviceId16,
6507
+ rootCauseNode: serviceId17,
6508
6508
  rootCauseReason: result.reason ?? "incompatible driver",
6509
6509
  ...result.minDriverVersion ? {
6510
6510
  fixRecommendation: `Upgrade ${svc.name} ${pair.driver} driver to >= ${result.minDriverVersion}`
@@ -6515,11 +6515,11 @@ function databaseRootCauseShape(graph, origin, walk10) {
6515
6515
  }
6516
6516
  return null;
6517
6517
  }
6518
- function serviceRootCauseShape(graph, _origin, walk10) {
6519
- for (const id of walk10.path) {
6518
+ function serviceRootCauseShape(graph, _origin, walk11) {
6519
+ for (const id of walk11.path) {
6520
6520
  const owner = resolveOwningService(graph, id);
6521
6521
  if (!owner) continue;
6522
- const { id: serviceId16, svc } = owner;
6522
+ const { id: serviceId17, svc } = owner;
6523
6523
  const deps = svc.dependencies ?? {};
6524
6524
  const serviceNodeEngine = svc.nodeEngine;
6525
6525
  for (const constraint of nodeEngineConstraints()) {
@@ -6528,7 +6528,7 @@ function serviceRootCauseShape(graph, _origin, walk10) {
6528
6528
  const result = checkNodeEngineConstraint(constraint, declared, serviceNodeEngine);
6529
6529
  if (!result.compatible && result.reason) {
6530
6530
  return {
6531
- rootCauseNode: serviceId16,
6531
+ rootCauseNode: serviceId17,
6532
6532
  rootCauseReason: result.reason,
6533
6533
  ...result.requiredNodeVersion ? {
6534
6534
  fixRecommendation: `Bump ${svc.name}'s engines.node to >= ${result.requiredNodeVersion}`
@@ -6543,7 +6543,7 @@ function serviceRootCauseShape(graph, _origin, walk10) {
6543
6543
  const result = checkPackageConflict(conflict, declared, requiredDeclared);
6544
6544
  if (!result.compatible && result.reason) {
6545
6545
  return {
6546
- rootCauseNode: serviceId16,
6546
+ rootCauseNode: serviceId17,
6547
6547
  rootCauseReason: result.reason,
6548
6548
  fixRecommendation: `Upgrade ${svc.name}'s ${conflict.requires.name} to >= ${conflict.requires.minVersion}`
6549
6549
  };
@@ -6552,15 +6552,15 @@ function serviceRootCauseShape(graph, _origin, walk10) {
6552
6552
  }
6553
6553
  return null;
6554
6554
  }
6555
- function fileRootCauseShape(graph, origin, walk10) {
6555
+ function fileRootCauseShape(graph, origin, walk11) {
6556
6556
  const owner = resolveOwningService(graph, origin.id);
6557
6557
  if (!owner) return null;
6558
- return serviceRootCauseShape(graph, owner.svc, walk10);
6558
+ return serviceRootCauseShape(graph, owner.svc, walk11);
6559
6559
  }
6560
- function symbolRootCauseShape(graph, origin, walk10) {
6560
+ function symbolRootCauseShape(graph, origin, walk11) {
6561
6561
  const owner = resolveOwningService(graph, origin.id);
6562
6562
  if (!owner) return null;
6563
- return serviceRootCauseShape(graph, owner.svc, walk10);
6563
+ return serviceRootCauseShape(graph, owner.svc, walk11);
6564
6564
  }
6565
6565
  var rootCauseShapes = {
6566
6566
  [import_types8.NodeType.DatabaseNode]: databaseRootCauseShape,
@@ -6573,8 +6573,8 @@ function legacyRootCause(graph, errorNodeId, errorEvent, incidents) {
6573
6573
  const origin = graph.getNodeAttributes(errorNodeId);
6574
6574
  const shape = rootCauseShapes[origin.type];
6575
6575
  if (shape) {
6576
- const walk10 = longestIncomingWalk(graph, errorNodeId, ROOT_CAUSE_MAX_DEPTH);
6577
- const match = shape(graph, origin, walk10);
6576
+ const walk11 = longestIncomingWalk(graph, errorNodeId, ROOT_CAUSE_MAX_DEPTH);
6577
+ const match = shape(graph, origin, walk11);
6578
6578
  if (match) {
6579
6579
  const reason = errorEvent ? `${match.rootCauseReason} (observed error: ${errorEvent.errorMessage})` : match.rootCauseReason;
6580
6580
  return {
@@ -6582,9 +6582,9 @@ function legacyRootCause(graph, errorNodeId, errorEvent, incidents) {
6582
6582
  result: import_types8.RootCauseResultSchema.parse({
6583
6583
  rootCauseNode: match.rootCauseNode,
6584
6584
  rootCauseReason: reason,
6585
- traversalPath: walk10.path,
6586
- edgeProvenances: walk10.edges.map((e) => e.provenance),
6587
- confidence: confidenceFromMix(walk10.edges),
6585
+ traversalPath: walk11.path,
6586
+ edgeProvenances: walk11.edges.map((e) => e.provenance),
6587
+ confidence: confidenceFromMix(walk11.edges),
6588
6588
  fixRecommendation: match.fixRecommendation
6589
6589
  })
6590
6590
  };
@@ -6648,9 +6648,9 @@ function rootCauseFromIncidents(nodeId, incidents, errorEvent) {
6648
6648
  function isFailingCallEdge(e) {
6649
6649
  return e.type === import_types8.EdgeType.CALLS && (e.signal?.errorCount ?? 0) > 0;
6650
6650
  }
6651
- function callSourcesForService(graph, serviceId16) {
6652
- const ids = [serviceId16];
6653
- for (const edgeId of graph.outboundEdges(serviceId16)) {
6651
+ function callSourcesForService(graph, serviceId17) {
6652
+ const ids = [serviceId17];
6653
+ for (const edgeId of graph.outboundEdges(serviceId17)) {
6654
6654
  const e = graph.getEdgeAttributes(edgeId);
6655
6655
  if (e.type !== import_types8.EdgeType.CONTAINS) continue;
6656
6656
  const tgt = graph.getNodeAttributes(e.target);
@@ -6674,9 +6674,9 @@ function failingCallDominates(e, id, curEdge, curId) {
6674
6674
  }
6675
6675
  return id < curId;
6676
6676
  }
6677
- function dominantFailingCall(graph, serviceId16, visited) {
6677
+ function dominantFailingCall(graph, serviceId17, visited) {
6678
6678
  let best = null;
6679
- for (const src of callSourcesForService(graph, serviceId16)) {
6679
+ for (const src of callSourcesForService(graph, serviceId17)) {
6680
6680
  for (const edgeId of graph.outboundEdges(src)) {
6681
6681
  const e = graph.getEdgeAttributes(edgeId);
6682
6682
  if (!isFailingCallEdge(e)) continue;
@@ -6691,20 +6691,20 @@ function dominantFailingCall(graph, serviceId16, visited) {
6691
6691
  return best;
6692
6692
  }
6693
6693
  function followFailingCallChain(graph, originServiceId, maxDepth) {
6694
- const path76 = [originServiceId];
6694
+ const path77 = [originServiceId];
6695
6695
  const edges = [];
6696
6696
  const visited = /* @__PURE__ */ new Set([originServiceId]);
6697
6697
  let current = originServiceId;
6698
6698
  for (let depth = 0; depth < maxDepth; depth++) {
6699
6699
  const hop = dominantFailingCall(graph, current, visited);
6700
6700
  if (!hop) break;
6701
- path76.push(hop.nextService);
6701
+ path77.push(hop.nextService);
6702
6702
  edges.push(hop.edge);
6703
6703
  visited.add(hop.nextService);
6704
6704
  current = hop.nextService;
6705
6705
  }
6706
6706
  if (edges.length === 0) return null;
6707
- return { path: path76, edges, culprit: current };
6707
+ return { path: path77, edges, culprit: current };
6708
6708
  }
6709
6709
  function isStaleCallEdge(e) {
6710
6710
  return e.type === import_types8.EdgeType.CALLS && e.provenance === import_types8.Provenance.STALE;
@@ -6715,9 +6715,9 @@ function staleCallDominates(e, id, curEdge, curId) {
6715
6715
  if (ev !== cv) return ev > cv;
6716
6716
  return id < curId;
6717
6717
  }
6718
- function dominantStaleCall(graph, serviceId16, visited) {
6718
+ function dominantStaleCall(graph, serviceId17, visited) {
6719
6719
  const bestByCallee = /* @__PURE__ */ new Map();
6720
- for (const src of callSourcesForService(graph, serviceId16)) {
6720
+ for (const src of callSourcesForService(graph, serviceId17)) {
6721
6721
  for (const edgeId of graph.outboundEdges(src)) {
6722
6722
  const e = graph.getEdgeAttributes(edgeId);
6723
6723
  if (e.type !== import_types8.EdgeType.CALLS) continue;
@@ -6740,26 +6740,26 @@ function dominantStaleCall(graph, serviceId16, visited) {
6740
6740
  return best;
6741
6741
  }
6742
6742
  function followStaleCallChain(graph, originServiceId, maxDepth) {
6743
- const path76 = [originServiceId];
6743
+ const path77 = [originServiceId];
6744
6744
  const edges = [];
6745
6745
  const visited = /* @__PURE__ */ new Set([originServiceId]);
6746
6746
  let current = originServiceId;
6747
6747
  for (let depth = 0; depth < maxDepth; depth++) {
6748
6748
  const hop = dominantStaleCall(graph, current, visited);
6749
6749
  if (!hop) break;
6750
- path76.push(hop.nextService);
6750
+ path77.push(hop.nextService);
6751
6751
  edges.push(hop.edge);
6752
6752
  visited.add(hop.nextService);
6753
6753
  current = hop.nextService;
6754
6754
  }
6755
6755
  if (edges.length === 0) return null;
6756
- return { path: path76, edges, culprit: current };
6756
+ return { path: path77, edges, culprit: current };
6757
6757
  }
6758
6758
  function crossServiceRootCause(graph, originId, incidents, errorEvent) {
6759
6759
  const chain = followFailingCallChain(graph, originId, ROOT_CAUSE_MAX_DEPTH);
6760
6760
  if (!chain) return null;
6761
6761
  const culprit = chain.culprit;
6762
- const path76 = [...chain.path];
6762
+ const path77 = [...chain.path];
6763
6763
  const edgeProvenances = chain.edges.map((e) => e.provenance);
6764
6764
  const baseConfidence = confidenceFromMix(chain.edges);
6765
6765
  const confidence = Math.max(0, Math.min(1, baseConfidence * INCIDENT_ROOT_CAUSE_CONFIDENCE));
@@ -6767,14 +6767,14 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
6767
6767
  if (loc) {
6768
6768
  let rootCauseNode = culprit;
6769
6769
  if (loc.fileNode) {
6770
- path76.push(loc.fileNode);
6770
+ path77.push(loc.fileNode);
6771
6771
  edgeProvenances.push(import_types8.Provenance.OBSERVED);
6772
6772
  rootCauseNode = loc.fileNode;
6773
6773
  }
6774
6774
  return import_types8.RootCauseResultSchema.parse({
6775
6775
  rootCauseNode,
6776
6776
  rootCauseReason: loc.rootCauseReason,
6777
- traversalPath: path76,
6777
+ traversalPath: path77,
6778
6778
  edgeProvenances,
6779
6779
  confidence,
6780
6780
  ...loc.fixRecommendation ? { fixRecommendation: loc.fixRecommendation } : {}
@@ -6786,7 +6786,7 @@ function crossServiceRootCause(graph, originId, incidents, errorEvent) {
6786
6786
  return import_types8.RootCauseResultSchema.parse({
6787
6787
  rootCauseNode: culprit,
6788
6788
  rootCauseReason: `${culpritName} is failing downstream calls (${errs} observed error${errs === 1 ? "" : "s"})`,
6789
- traversalPath: path76,
6789
+ traversalPath: path77,
6790
6790
  edgeProvenances,
6791
6791
  confidence,
6792
6792
  fixRecommendation: `Inspect ${culpritName}'s failing handler`
@@ -7399,10 +7399,10 @@ function enrichWithNavigation(graph, errorNodeId, tagged, incidents, now) {
7399
7399
  traversalPath = staleChain.path;
7400
7400
  edgeProvenances = staleChain.edges.map((e) => e.provenance);
7401
7401
  } else if (top.node !== seedNode) {
7402
- const path76 = findPath(graph, errorNodeId, top.node, "up", ROOT_CAUSE_MAX_DEPTH);
7403
- if (path76) {
7404
- traversalPath = path76.nodes;
7405
- edgeProvenances = path76.edges.map((e) => e.provenance);
7402
+ const path77 = findPath(graph, errorNodeId, top.node, "up", ROOT_CAUSE_MAX_DEPTH);
7403
+ if (path77) {
7404
+ traversalPath = path77.nodes;
7405
+ edgeProvenances = path77.edges.map((e) => e.provenance);
7406
7406
  } else {
7407
7407
  traversalPath = [errorNodeId, top.node];
7408
7408
  edgeProvenances = [top.provenance ?? import_types8.Provenance.OBSERVED];
@@ -7950,10 +7950,10 @@ function datastoreEverObserved(graph, nodeId) {
7950
7950
  }
7951
7951
  return false;
7952
7952
  }
7953
- function serviceHasObservedSameEngineStore(graph, buckets2, serviceId16, engine, excludeTarget) {
7953
+ function serviceHasObservedSameEngineStore(graph, buckets2, serviceId17, engine, excludeTarget) {
7954
7954
  for (const bucket of buckets2.values()) {
7955
7955
  if (bucket.type !== import_types9.EdgeType.CONNECTS_TO) continue;
7956
- if (bucket.source !== serviceId16) continue;
7956
+ if (bucket.source !== serviceId17) continue;
7957
7957
  if (bucket.target === excludeTarget) continue;
7958
7958
  if (!graph.hasNode(bucket.target)) continue;
7959
7959
  const target = graph.getNodeAttributes(bucket.target);
@@ -9041,9 +9041,9 @@ var K8S_KINDS_WITH_HOSTNAMES = /* @__PURE__ */ new Set([
9041
9041
  "StatefulSet",
9042
9042
  "DaemonSet"
9043
9043
  ]);
9044
- function addAliases(graph, serviceId16, candidates) {
9045
- if (!graph.hasNode(serviceId16)) return;
9046
- const node = graph.getNodeAttributes(serviceId16);
9044
+ function addAliases(graph, serviceId17, candidates) {
9045
+ if (!graph.hasNode(serviceId17)) return;
9046
+ const node = graph.getNodeAttributes(serviceId17);
9047
9047
  if (node.type !== import_types20.NodeType.ServiceNode) return;
9048
9048
  const set = new Set(node.aliases ?? []);
9049
9049
  for (const c of candidates) {
@@ -9053,7 +9053,7 @@ function addAliases(graph, serviceId16, candidates) {
9053
9053
  }
9054
9054
  if (set.size === 0) return;
9055
9055
  const updated = { ...node, aliases: [...set].sort() };
9056
- graph.replaceNodeAttributes(serviceId16, updated);
9056
+ graph.replaceNodeAttributes(serviceId17, updated);
9057
9057
  }
9058
9058
  function indexServicesByName(services) {
9059
9059
  const map = /* @__PURE__ */ new Map();
@@ -9086,12 +9086,12 @@ async function collectComposeAliases(graph, scanPath, serviceIndex) {
9086
9086
  }
9087
9087
  if (!compose?.services) return;
9088
9088
  for (const [composeName, svc] of Object.entries(compose.services)) {
9089
- const serviceId16 = serviceIndex.get(composeName);
9090
- if (!serviceId16) continue;
9089
+ const serviceId17 = serviceIndex.get(composeName);
9090
+ if (!serviceId17) continue;
9091
9091
  const aliases = /* @__PURE__ */ new Set([composeName]);
9092
9092
  if (svc.container_name) aliases.add(svc.container_name);
9093
9093
  if (svc.hostname) aliases.add(svc.hostname);
9094
- addAliases(graph, serviceId16, aliases);
9094
+ addAliases(graph, serviceId17, aliases);
9095
9095
  }
9096
9096
  }
9097
9097
  var LABEL_KEYS = /* @__PURE__ */ new Set([
@@ -10202,7 +10202,7 @@ async function addSymbolEdges(graph, services) {
10202
10202
  return best;
10203
10203
  };
10204
10204
  const requests = [];
10205
- const walk10 = (node) => {
10205
+ const walk11 = (node) => {
10206
10206
  if (node.type === "class_declaration" || node.type === "abstract_class_declaration" || node.type === "class") {
10207
10207
  const self = localBySpan.get(`${node.startPosition.row + 1}:${node.endPosition.row + 1}`);
10208
10208
  if (self && self.kind === "class") {
@@ -10248,10 +10248,10 @@ async function addSymbolEdges(graph, services) {
10248
10248
  }
10249
10249
  for (let i = 0; i < node.namedChildCount; i++) {
10250
10250
  const child = node.namedChild(i);
10251
- if (child) walk10(child);
10251
+ if (child) walk11(child);
10252
10252
  }
10253
10253
  };
10254
- walk10(root);
10254
+ walk11(root);
10255
10255
  for (const req of requests) {
10256
10256
  const targetSid = resolveTarget(req.targetName, req.wantKind);
10257
10257
  if (!targetSid) continue;
@@ -11423,7 +11423,7 @@ var import_types25 = require("@neat.is/types");
11423
11423
  async function walkConfigFiles(dir, excludeDirs = []) {
11424
11424
  const excluded = new Set(excludeDirs.map((d) => import_node_path37.default.resolve(d)));
11425
11425
  const out = [];
11426
- async function walk10(current) {
11426
+ async function walk11(current) {
11427
11427
  const entries = await import_node_fs25.promises.readdir(current, { withFileTypes: true });
11428
11428
  for (const entry of entries) {
11429
11429
  const full = import_node_path37.default.join(current, entry.name);
@@ -11431,13 +11431,13 @@ async function walkConfigFiles(dir, excludeDirs = []) {
11431
11431
  if (IGNORED_DIRS.has(entry.name)) continue;
11432
11432
  if (excluded.has(import_node_path37.default.resolve(full))) continue;
11433
11433
  if (await isPythonVenvDir(full)) continue;
11434
- await walk10(full);
11434
+ await walk11(full);
11435
11435
  } else if (entry.isFile() && isConfigFile(entry.name).match) {
11436
11436
  out.push(full);
11437
11437
  }
11438
11438
  }
11439
11439
  }
11440
- await walk10(dir);
11440
+ await walk11(dir);
11441
11441
  return out;
11442
11442
  }
11443
11443
  async function addConfigNodes(graph, services, scanPath) {
@@ -11528,7 +11528,7 @@ function grpcMethodsFromProto(content, fqPackage) {
11528
11528
  async function walkProtoFiles(dir, excludeDirs = []) {
11529
11529
  const excluded = new Set(excludeDirs.map((d) => import_node_path38.default.resolve(d)));
11530
11530
  const out = [];
11531
- async function walk10(current) {
11531
+ async function walk11(current) {
11532
11532
  const entries = await import_node_fs26.promises.readdir(current, { withFileTypes: true }).catch(() => []);
11533
11533
  for (const entry of entries) {
11534
11534
  const full = import_node_path38.default.join(current, entry.name);
@@ -11536,13 +11536,13 @@ async function walkProtoFiles(dir, excludeDirs = []) {
11536
11536
  if (IGNORED_DIRS.has(entry.name)) continue;
11537
11537
  if (excluded.has(import_node_path38.default.resolve(full))) continue;
11538
11538
  if (await isPythonVenvDir(full)) continue;
11539
- await walk10(full);
11539
+ await walk11(full);
11540
11540
  } else if (entry.isFile() && import_node_path38.default.extname(entry.name) === PROTO_EXTENSION) {
11541
11541
  out.push(full);
11542
11542
  }
11543
11543
  }
11544
11544
  }
11545
- await walk10(dir);
11545
+ await walk11(dir);
11546
11546
  return out;
11547
11547
  }
11548
11548
  async function addGrpcMethods(graph, services) {
@@ -11610,7 +11610,7 @@ async function addGrpcMethods(graph, services) {
11610
11610
 
11611
11611
  // src/extract/calls/index.ts
11612
11612
  init_cjs_shims();
11613
- var import_types45 = require("@neat.is/types");
11613
+ var import_types46 = require("@neat.is/types");
11614
11614
 
11615
11615
  // src/extract/calls/http.ts
11616
11616
  init_cjs_shims();
@@ -12545,7 +12545,7 @@ function isFirestoreClientFactory(node) {
12545
12545
  }
12546
12546
  function firestoreClientVars(root) {
12547
12547
  const vars = /* @__PURE__ */ new Set();
12548
- const walk10 = (node) => {
12548
+ const walk11 = (node) => {
12549
12549
  if (node.type === "variable_declarator") {
12550
12550
  const name = node.childForFieldName("name");
12551
12551
  let value = node.childForFieldName("value");
@@ -12554,9 +12554,9 @@ function firestoreClientVars(root) {
12554
12554
  vars.add(name.text);
12555
12555
  }
12556
12556
  }
12557
- for (const c of namedChildren(node)) walk10(c);
12557
+ for (const c of namedChildren(node)) walk11(c);
12558
12558
  };
12559
- walk10(root);
12559
+ walk11(root);
12560
12560
  return vars;
12561
12561
  }
12562
12562
  function isClientExpr(node, clientVars) {
@@ -12711,7 +12711,7 @@ function firestoreEndpointsFromFile(file, serviceDir) {
12711
12711
  }
12712
12712
  s.add(field);
12713
12713
  };
12714
- const walk10 = (node) => {
12714
+ const walk11 = (node) => {
12715
12715
  if (node.type === "call_expression") {
12716
12716
  const fn = node.childForFieldName("function");
12717
12717
  const line = node.startPosition.row + 1;
@@ -12751,9 +12751,9 @@ function firestoreEndpointsFromFile(file, serviceDir) {
12751
12751
  }
12752
12752
  }
12753
12753
  }
12754
- for (const c of namedChildren(node)) walk10(c);
12754
+ for (const c of namedChildren(node)) walk11(c);
12755
12755
  };
12756
- walk10(tree.rootNode);
12756
+ walk11(tree.rootNode);
12757
12757
  const out = [];
12758
12758
  for (const [collPath, line] of collLine) {
12759
12759
  const byField = writes.get(collPath);
@@ -13369,13 +13369,13 @@ function pythonOrmCrossFileEndpoints(files, serviceDir) {
13369
13369
  return out;
13370
13370
  }
13371
13371
 
13372
- // src/extract/calls/django-orm.ts
13372
+ // src/extract/calls/socket.ts
13373
13373
  init_cjs_shims();
13374
13374
  var import_node_path49 = __toESM(require("path"), 1);
13375
13375
  var import_tree_sitter10 = __toESM(require("tree-sitter"), 1);
13376
13376
  var import_tree_sitter_python6 = __toESM(require("tree-sitter-python"), 1);
13377
13377
  var import_types37 = require("@neat.is/types");
13378
- var DJANGO_IMPORT_RE = /(?:from|import)\s+django\b/;
13378
+ var SOCKET_IMPORT_RE = /(?:^|\n)\s*(?:import\s+socket\b|from\s+socket\s+import\b)/;
13379
13379
  var PARSE_CHUNK7 = 16384;
13380
13380
  function makePyParser4() {
13381
13381
  const p = new import_tree_sitter10.default();
@@ -13395,22 +13395,109 @@ function namedChildren3(node) {
13395
13395
  }
13396
13396
  return out;
13397
13397
  }
13398
+ function walk4(node, visit) {
13399
+ visit(node);
13400
+ for (const c of namedChildren3(node)) walk4(c, visit);
13401
+ }
13398
13402
  function pyStaticStringText3(node) {
13399
13403
  if (node.type !== "string") return null;
13400
- for (const c of namedChildren3(node)) {
13404
+ for (const child of namedChildren3(node)) {
13405
+ if (child.type === "interpolation") return null;
13406
+ if (child.type === "string_content") return child.text;
13407
+ }
13408
+ return "";
13409
+ }
13410
+ function hasSocketConstructor(root) {
13411
+ let found = false;
13412
+ walk4(root, (n) => {
13413
+ if (found || n.type !== "call") return;
13414
+ const t = n.childForFieldName("function")?.text;
13415
+ if (t === "socket.socket" || t === "socket") found = true;
13416
+ });
13417
+ return found;
13418
+ }
13419
+ function socketEndpointsFromFile(file, serviceDir) {
13420
+ if (!SOCKET_IMPORT_RE.test(file.content)) return [];
13421
+ const tree = parseSource7(makePyParser4(), file.content);
13422
+ if (!hasSocketConstructor(tree.rootNode)) return [];
13423
+ const out = [];
13424
+ const seen = /* @__PURE__ */ new Set();
13425
+ walk4(tree.rootNode, (node) => {
13426
+ if (node.type !== "call") return;
13427
+ const fn = node.childForFieldName("function");
13428
+ if (fn?.type !== "attribute" || fn.childForFieldName("attribute")?.text !== "connect") return;
13429
+ const args = node.childForFieldName("arguments");
13430
+ const first = args ? namedChildren3(args).find((a) => a.type !== "keyword_argument") : void 0;
13431
+ if (!first || first.type !== "tuple") return;
13432
+ const elems = namedChildren3(first);
13433
+ if (elems.length < 2) return;
13434
+ const hostNode = elems[0];
13435
+ const host = hostNode.type === "string" ? pyStaticStringText3(hostNode) : null;
13436
+ const portNode = elems[1];
13437
+ const port = portNode.type === "integer" ? portNode.text : null;
13438
+ const name = host ? port ? `${host}:${port}` : host : "env";
13439
+ if (seen.has(name)) return;
13440
+ seen.add(name);
13441
+ const line = node.startPosition.row + 1;
13442
+ out.push({
13443
+ infraId: (0, import_types37.infraId)("socket", name),
13444
+ name,
13445
+ kind: "socket",
13446
+ edgeType: "CALLS",
13447
+ // A verified `socket.socket(...)` + `.connect((host, port))` call site.
13448
+ confidenceKind: "verified-call-site",
13449
+ evidence: {
13450
+ file: import_node_path49.default.relative(serviceDir, file.path),
13451
+ line,
13452
+ snippet: snippet(file.content, line)
13453
+ }
13454
+ });
13455
+ });
13456
+ return out;
13457
+ }
13458
+
13459
+ // src/extract/calls/django-orm.ts
13460
+ init_cjs_shims();
13461
+ var import_node_path50 = __toESM(require("path"), 1);
13462
+ var import_tree_sitter11 = __toESM(require("tree-sitter"), 1);
13463
+ var import_tree_sitter_python7 = __toESM(require("tree-sitter-python"), 1);
13464
+ var import_types38 = require("@neat.is/types");
13465
+ var DJANGO_IMPORT_RE = /(?:from|import)\s+django\b/;
13466
+ var PARSE_CHUNK8 = 16384;
13467
+ function makePyParser5() {
13468
+ const p = new import_tree_sitter11.default();
13469
+ p.setLanguage(import_tree_sitter_python7.default);
13470
+ return p;
13471
+ }
13472
+ function parseSource8(parser, source) {
13473
+ return parser.parse(
13474
+ (index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK8)
13475
+ );
13476
+ }
13477
+ function namedChildren4(node) {
13478
+ const out = [];
13479
+ for (let i = 0; i < node.namedChildCount; i++) {
13480
+ const c = node.namedChild(i);
13481
+ if (c) out.push(c);
13482
+ }
13483
+ return out;
13484
+ }
13485
+ function pyStaticStringText4(node) {
13486
+ if (node.type !== "string") return null;
13487
+ for (const c of namedChildren4(node)) {
13401
13488
  if (c.type === "interpolation") return null;
13402
13489
  if (c.type === "string_content") return c.text;
13403
13490
  }
13404
13491
  return "";
13405
13492
  }
13406
- function walk4(node, visit) {
13493
+ function walk5(node, visit) {
13407
13494
  visit(node);
13408
- for (const c of namedChildren3(node)) walk4(c, visit);
13495
+ for (const c of namedChildren4(node)) walk5(c, visit);
13409
13496
  }
13410
13497
  function extendsDjangoModel(cls) {
13411
13498
  const supers = cls.childForFieldName("superclasses");
13412
13499
  if (!supers) return false;
13413
- for (const a of namedChildren3(supers)) {
13500
+ for (const a of namedChildren4(supers)) {
13414
13501
  const t = a.text;
13415
13502
  if (t === "models.Model" || t === "Model" || t.endsWith(".Model")) return true;
13416
13503
  }
@@ -13418,31 +13505,31 @@ function extendsDjangoModel(cls) {
13418
13505
  }
13419
13506
  function readMeta(body) {
13420
13507
  const out = {};
13421
- for (const stmt of namedChildren3(body)) {
13508
+ for (const stmt of namedChildren4(body)) {
13422
13509
  if (stmt.type !== "class_definition") continue;
13423
13510
  if (stmt.childForFieldName("name")?.text !== "Meta") continue;
13424
13511
  const metaBody = stmt.childForFieldName("body");
13425
13512
  if (!metaBody) continue;
13426
- for (const ms of namedChildren3(metaBody)) {
13513
+ for (const ms of namedChildren4(metaBody)) {
13427
13514
  if (ms.type !== "expression_statement") continue;
13428
13515
  const a = ms.namedChild(0);
13429
13516
  if (a?.type !== "assignment") continue;
13430
13517
  const l = a.childForFieldName("left")?.text;
13431
13518
  const r = a.childForFieldName("right");
13432
13519
  if (r?.type !== "string") continue;
13433
- if (l === "db_table") out.dbTable = pyStaticStringText3(r) ?? void 0;
13434
- if (l === "app_label") out.appLabel = pyStaticStringText3(r) ?? void 0;
13520
+ if (l === "db_table") out.dbTable = pyStaticStringText4(r) ?? void 0;
13521
+ if (l === "app_label") out.appLabel = pyStaticStringText4(r) ?? void 0;
13435
13522
  }
13436
13523
  }
13437
13524
  return out;
13438
13525
  }
13439
13526
  function djangoOrmEndpointsFromFile(file, serviceDir) {
13440
13527
  if (!DJANGO_IMPORT_RE.test(file.content)) return [];
13441
- const tree = parseSource7(makePyParser4(), file.content);
13528
+ const tree = parseSource8(makePyParser5(), file.content);
13442
13529
  const out = [];
13443
13530
  const seen = /* @__PURE__ */ new Set();
13444
- const defaultAppLabel = import_node_path49.default.basename(import_node_path49.default.dirname(file.path));
13445
- walk4(tree.rootNode, (node) => {
13531
+ const defaultAppLabel = import_node_path50.default.basename(import_node_path50.default.dirname(file.path));
13532
+ walk5(tree.rootNode, (node) => {
13446
13533
  if (node.type !== "class_definition") return;
13447
13534
  if (!extendsDjangoModel(node)) return;
13448
13535
  const nameNode = node.childForFieldName("name");
@@ -13454,12 +13541,12 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
13454
13541
  seen.add(table);
13455
13542
  const line = node.startPosition.row + 1;
13456
13543
  out.push({
13457
- infraId: (0, import_types37.infraId)("sql-table", table),
13544
+ infraId: (0, import_types38.infraId)("sql-table", table),
13458
13545
  name: table,
13459
13546
  kind: "sql-table",
13460
13547
  edgeType: "CALLS",
13461
13548
  confidenceKind: "verified-call-site",
13462
- evidence: { file: import_node_path49.default.relative(serviceDir, file.path), line, snippet: snippet(file.content, line) }
13549
+ evidence: { file: import_node_path50.default.relative(serviceDir, file.path), line, snippet: snippet(file.content, line) }
13463
13550
  });
13464
13551
  });
13465
13552
  return out;
@@ -13467,18 +13554,18 @@ function djangoOrmEndpointsFromFile(file, serviceDir) {
13467
13554
 
13468
13555
  // src/extract/calls/drizzle.ts
13469
13556
  init_cjs_shims();
13470
- var import_node_path50 = __toESM(require("path"), 1);
13471
- var import_tree_sitter11 = __toESM(require("tree-sitter"), 1);
13557
+ var import_node_path51 = __toESM(require("path"), 1);
13558
+ var import_tree_sitter12 = __toESM(require("tree-sitter"), 1);
13472
13559
  var import_tree_sitter_javascript7 = __toESM(require("tree-sitter-javascript"), 1);
13473
- var import_types38 = require("@neat.is/types");
13560
+ var import_types39 = require("@neat.is/types");
13474
13561
  var DRIZZLE_IMPORT_RE = /drizzle-orm/;
13475
13562
  var TABLE_BUILDERS = /* @__PURE__ */ new Set(["pgTable", "mysqlTable", "sqliteTable"]);
13476
13563
  function parserForExt3(ext) {
13477
- const p = new import_tree_sitter11.default();
13564
+ const p = new import_tree_sitter12.default();
13478
13565
  p.setLanguage(GRAMMAR_BY_EXT[ext] ?? import_tree_sitter_javascript7.default);
13479
13566
  return p;
13480
13567
  }
13481
- function namedChildren4(node) {
13568
+ function namedChildren5(node) {
13482
13569
  const out = [];
13483
13570
  for (let i = 0; i < node.namedChildCount; i++) {
13484
13571
  const c = node.namedChild(i);
@@ -13488,7 +13575,7 @@ function namedChildren4(node) {
13488
13575
  }
13489
13576
  function stringLiteralText4(node) {
13490
13577
  if (!node || node.type !== "string") return null;
13491
- for (const child of namedChildren4(node)) {
13578
+ for (const child of namedChildren5(node)) {
13492
13579
  if (child.type === "string_fragment") return child.text;
13493
13580
  }
13494
13581
  return "";
@@ -13496,7 +13583,7 @@ function stringLiteralText4(node) {
13496
13583
  function firstStringArg(call) {
13497
13584
  const args = call.childForFieldName("arguments");
13498
13585
  if (!args) return null;
13499
- for (const arg of namedChildren4(args)) {
13586
+ for (const arg of namedChildren5(args)) {
13500
13587
  if (arg.type === "string") return stringLiteralText4(arg);
13501
13588
  return null;
13502
13589
  }
@@ -13531,7 +13618,7 @@ function keyName2(key) {
13531
13618
  function columnsFromObject(obj) {
13532
13619
  const out = [];
13533
13620
  const seen = /* @__PURE__ */ new Set();
13534
- for (const child of namedChildren4(obj)) {
13621
+ for (const child of namedChildren5(obj)) {
13535
13622
  if (child.type !== "pair") continue;
13536
13623
  const value = child.childForFieldName("value");
13537
13624
  const key = keyName2(child.childForFieldName("key"));
@@ -13545,15 +13632,15 @@ function columnsFromObject(obj) {
13545
13632
  }
13546
13633
  function drizzleEndpointsFromFile(file, serviceDir) {
13547
13634
  if (!DRIZZLE_IMPORT_RE.test(file.content)) return [];
13548
- const tree = parseSource3(parserForExt3(import_node_path50.default.extname(file.path)), file.content);
13635
+ const tree = parseSource3(parserForExt3(import_node_path51.default.extname(file.path)), file.content);
13549
13636
  const out = [];
13550
13637
  const seen = /* @__PURE__ */ new Set();
13551
- const walk10 = (node) => {
13638
+ const walk11 = (node) => {
13552
13639
  if (node.type === "call_expression") {
13553
13640
  const fn = node.childForFieldName("function");
13554
13641
  if (fn?.type === "identifier" && TABLE_BUILDERS.has(fn.text)) {
13555
13642
  const args = node.childForFieldName("arguments");
13556
- const argNodes = args ? namedChildren4(args) : [];
13643
+ const argNodes = args ? namedChildren5(args) : [];
13557
13644
  const tableName = stringLiteralText4(argNodes[0] ?? null);
13558
13645
  const obj = argNodes[1];
13559
13646
  if (tableName && obj?.type === "object" && !seen.has(tableName)) {
@@ -13561,14 +13648,14 @@ function drizzleEndpointsFromFile(file, serviceDir) {
13561
13648
  const columns = columnsFromObject(obj);
13562
13649
  const line = node.startPosition.row + 1;
13563
13650
  out.push({
13564
- infraId: (0, import_types38.infraId)("sql-table", tableName),
13651
+ infraId: (0, import_types39.infraId)("sql-table", tableName),
13565
13652
  name: tableName,
13566
13653
  kind: "sql-table",
13567
13654
  edgeType: "CALLS",
13568
13655
  confidenceKind: "structural",
13569
13656
  columns,
13570
13657
  evidence: {
13571
- file: import_node_path50.default.relative(serviceDir, file.path),
13658
+ file: import_node_path51.default.relative(serviceDir, file.path),
13572
13659
  line,
13573
13660
  snippet: snippet(file.content, line)
13574
13661
  }
@@ -13576,9 +13663,9 @@ function drizzleEndpointsFromFile(file, serviceDir) {
13576
13663
  }
13577
13664
  }
13578
13665
  }
13579
- for (const c of namedChildren4(node)) walk10(c);
13666
+ for (const c of namedChildren5(node)) walk11(c);
13580
13667
  };
13581
- walk10(tree.rootNode);
13668
+ walk11(tree.rootNode);
13582
13669
  return out;
13583
13670
  }
13584
13671
  function enclosingVarName(call) {
@@ -13600,12 +13687,12 @@ function enclosingVarName(call) {
13600
13687
  function collectDrizzleTables(root) {
13601
13688
  const tables = [];
13602
13689
  const varToTable = /* @__PURE__ */ new Map();
13603
- const walk10 = (node) => {
13690
+ const walk11 = (node) => {
13604
13691
  if (node.type === "call_expression") {
13605
13692
  const fn = node.childForFieldName("function");
13606
13693
  if (fn?.type === "identifier" && TABLE_BUILDERS.has(fn.text)) {
13607
13694
  const args = node.childForFieldName("arguments");
13608
- const argNodes = args ? namedChildren4(args) : [];
13695
+ const argNodes = args ? namedChildren5(args) : [];
13609
13696
  const tableName = stringLiteralText4(argNodes[0] ?? null);
13610
13697
  const obj = argNodes[1]?.type === "object" ? argNodes[1] : null;
13611
13698
  if (tableName) {
@@ -13615,9 +13702,9 @@ function collectDrizzleTables(root) {
13615
13702
  }
13616
13703
  }
13617
13704
  }
13618
- for (const c of namedChildren4(node)) walk10(c);
13705
+ for (const c of namedChildren5(node)) walk11(c);
13619
13706
  };
13620
- walk10(root);
13707
+ walk11(root);
13621
13708
  return { tables, varToTable };
13622
13709
  }
13623
13710
  function referencesTargetVar(call) {
@@ -13625,7 +13712,7 @@ function referencesTargetVar(call) {
13625
13712
  if (fn?.type !== "member_expression") return null;
13626
13713
  if (fn.childForFieldName("property")?.text !== "references") return null;
13627
13714
  const args = call.childForFieldName("arguments");
13628
- const first = args ? namedChildren4(args)[0] ?? null : null;
13715
+ const first = args ? namedChildren5(args)[0] ?? null : null;
13629
13716
  if (first?.type !== "arrow_function") return null;
13630
13717
  const body = first.childForFieldName("body");
13631
13718
  if (body?.type !== "member_expression") return null;
@@ -13634,13 +13721,13 @@ function referencesTargetVar(call) {
13634
13721
  }
13635
13722
  function drizzleForeignKeys(file, serviceDir) {
13636
13723
  if (!DRIZZLE_IMPORT_RE.test(file.content)) return [];
13637
- const tree = parseSource3(parserForExt3(import_node_path50.default.extname(file.path)), file.content);
13724
+ const tree = parseSource3(parserForExt3(import_node_path51.default.extname(file.path)), file.content);
13638
13725
  const { tables, varToTable } = collectDrizzleTables(tree.rootNode);
13639
13726
  const out = [];
13640
13727
  const seen = /* @__PURE__ */ new Set();
13641
13728
  for (const table of tables) {
13642
13729
  if (!table.object) continue;
13643
- const walk10 = (node) => {
13730
+ const walk11 = (node) => {
13644
13731
  if (node.type === "call_expression") {
13645
13732
  const targetVar = referencesTargetVar(node);
13646
13733
  const parentTable = targetVar ? varToTable.get(targetVar) : void 0;
@@ -13653,7 +13740,7 @@ function drizzleForeignKeys(file, serviceDir) {
13653
13740
  childTable: table.tableName,
13654
13741
  parentTable,
13655
13742
  evidence: {
13656
- file: import_node_path50.default.relative(serviceDir, file.path),
13743
+ file: import_node_path51.default.relative(serviceDir, file.path),
13657
13744
  line,
13658
13745
  snippet: snippet(file.content, line)
13659
13746
  }
@@ -13661,17 +13748,17 @@ function drizzleForeignKeys(file, serviceDir) {
13661
13748
  }
13662
13749
  }
13663
13750
  }
13664
- for (const c of namedChildren4(node)) walk10(c);
13751
+ for (const c of namedChildren5(node)) walk11(c);
13665
13752
  };
13666
- walk10(table.object);
13753
+ walk11(table.object);
13667
13754
  }
13668
13755
  return out;
13669
13756
  }
13670
13757
 
13671
13758
  // src/extract/calls/prisma.ts
13672
13759
  init_cjs_shims();
13673
- var import_node_path51 = __toESM(require("path"), 1);
13674
- var import_types39 = require("@neat.is/types");
13760
+ var import_node_path52 = __toESM(require("path"), 1);
13761
+ var import_types40 = require("@neat.is/types");
13675
13762
  var SCALAR_TYPES = /* @__PURE__ */ new Set([
13676
13763
  "Int",
13677
13764
  "String",
@@ -13719,14 +13806,14 @@ function prismaColumnsFromSchema(file, serviceDir) {
13719
13806
  if (seenTable.has(b.tableName)) return;
13720
13807
  seenTable.add(b.tableName);
13721
13808
  out.push({
13722
- infraId: (0, import_types39.infraId)("sql-table", b.tableName),
13809
+ infraId: (0, import_types40.infraId)("sql-table", b.tableName),
13723
13810
  name: b.tableName,
13724
13811
  kind: "sql-table",
13725
13812
  edgeType: "CALLS",
13726
13813
  confidenceKind: "structural",
13727
13814
  columns: b.columns,
13728
13815
  evidence: {
13729
- file: import_node_path51.default.relative(serviceDir, file.path),
13816
+ file: import_node_path52.default.relative(serviceDir, file.path),
13730
13817
  line: b.startLine,
13731
13818
  snippet: snippet(content, b.startLine)
13732
13819
  }
@@ -13787,7 +13874,7 @@ function prismaColumnsFromSchema(file, serviceDir) {
13787
13874
  }
13788
13875
  async function prismaColumnEndpoints(serviceDir) {
13789
13876
  const schemaPath = await findFirst(serviceDir, [
13790
- import_node_path51.default.join("prisma", "schema.prisma"),
13877
+ import_node_path52.default.join("prisma", "schema.prisma"),
13791
13878
  "schema.prisma"
13792
13879
  ]);
13793
13880
  if (!schemaPath) return [];
@@ -13862,7 +13949,7 @@ function prismaForeignKeysFromSchema(file, serviceDir) {
13862
13949
  childTable: current.table,
13863
13950
  parentTable,
13864
13951
  evidence: {
13865
- file: import_node_path51.default.relative(serviceDir, file.path),
13952
+ file: import_node_path52.default.relative(serviceDir, file.path),
13866
13953
  line: lineNo,
13867
13954
  snippet: snippet(content, lineNo)
13868
13955
  }
@@ -13877,7 +13964,7 @@ function prismaForeignKeysFromSchema(file, serviceDir) {
13877
13964
  }
13878
13965
  async function prismaForeignKeys(serviceDir) {
13879
13966
  const schemaPath = await findFirst(serviceDir, [
13880
- import_node_path51.default.join("prisma", "schema.prisma"),
13967
+ import_node_path52.default.join("prisma", "schema.prisma"),
13881
13968
  "schema.prisma"
13882
13969
  ]);
13883
13970
  if (!schemaPath) return [];
@@ -13888,27 +13975,27 @@ async function prismaForeignKeys(serviceDir) {
13888
13975
 
13889
13976
  // src/extract/calls/activerecord.ts
13890
13977
  init_cjs_shims();
13891
- var import_node_path52 = __toESM(require("path"), 1);
13892
- var import_tree_sitter12 = __toESM(require("tree-sitter"), 1);
13978
+ var import_node_path53 = __toESM(require("path"), 1);
13979
+ var import_tree_sitter13 = __toESM(require("tree-sitter"), 1);
13893
13980
  var import_tree_sitter_ruby3 = __toESM(require("tree-sitter-ruby"), 1);
13894
- var import_types40 = require("@neat.is/types");
13981
+ var import_types41 = require("@neat.is/types");
13895
13982
  var AR_SCHEMA_RE = /ActiveRecord::Schema/;
13896
- var PARSE_CHUNK8 = 16384;
13983
+ var PARSE_CHUNK9 = 16384;
13897
13984
  function makeRubyParser2() {
13898
- const p = new import_tree_sitter12.default();
13985
+ const p = new import_tree_sitter13.default();
13899
13986
  p.setLanguage(import_tree_sitter_ruby3.default);
13900
13987
  return p;
13901
13988
  }
13902
- function parseSource8(parser, source) {
13989
+ function parseSource9(parser, source) {
13903
13990
  return parser.parse(
13904
- (index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK8)
13991
+ (index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK9)
13905
13992
  );
13906
13993
  }
13907
- function walk5(node, visit) {
13994
+ function walk6(node, visit) {
13908
13995
  visit(node);
13909
13996
  for (let i = 0; i < node.namedChildCount; i++) {
13910
13997
  const c = node.namedChild(i);
13911
- if (c) walk5(c, visit);
13998
+ if (c) walk6(c, visit);
13912
13999
  }
13913
14000
  }
13914
14001
  function rubyLiteral2(node) {
@@ -14079,24 +14166,24 @@ function readCreateTable(call) {
14079
14166
  }
14080
14167
  function railsSchemaEndpointsFromFile(file, serviceDir) {
14081
14168
  if (!AR_SCHEMA_RE.test(file.content)) return [];
14082
- const tree = parseSource8(makeRubyParser2(), file.content);
14169
+ const tree = parseSource9(makeRubyParser2(), file.content);
14083
14170
  const out = [];
14084
14171
  const seen = /* @__PURE__ */ new Set();
14085
- walk5(tree.rootNode, (node) => {
14172
+ walk6(tree.rootNode, (node) => {
14086
14173
  if (node.type !== "call") return;
14087
14174
  if (blockCallMethod(node) !== "create_table") return;
14088
14175
  const table = readCreateTable(node);
14089
14176
  if (!table || seen.has(table.name)) return;
14090
14177
  seen.add(table.name);
14091
14178
  out.push({
14092
- infraId: (0, import_types40.infraId)("sql-table", table.name),
14179
+ infraId: (0, import_types41.infraId)("sql-table", table.name),
14093
14180
  name: table.name,
14094
14181
  kind: "sql-table",
14095
14182
  edgeType: "CALLS",
14096
14183
  confidenceKind: "structural",
14097
14184
  ...table.columns.length > 0 ? { columns: table.columns } : {},
14098
14185
  evidence: {
14099
- file: import_node_path52.default.relative(serviceDir, file.path),
14186
+ file: import_node_path53.default.relative(serviceDir, file.path),
14100
14187
  line: table.line,
14101
14188
  snippet: snippet(file.content, table.line)
14102
14189
  }
@@ -14106,7 +14193,7 @@ function railsSchemaEndpointsFromFile(file, serviceDir) {
14106
14193
  }
14107
14194
  function railsSchemaForeignKeys(file, serviceDir) {
14108
14195
  if (!AR_SCHEMA_RE.test(file.content)) return [];
14109
- const tree = parseSource8(makeRubyParser2(), file.content);
14196
+ const tree = parseSource9(makeRubyParser2(), file.content);
14110
14197
  const out = [];
14111
14198
  const seen = /* @__PURE__ */ new Set();
14112
14199
  const emit = (childTable, parentTable, line) => {
@@ -14118,13 +14205,13 @@ function railsSchemaForeignKeys(file, serviceDir) {
14118
14205
  childTable,
14119
14206
  parentTable,
14120
14207
  evidence: {
14121
- file: import_node_path52.default.relative(serviceDir, file.path),
14208
+ file: import_node_path53.default.relative(serviceDir, file.path),
14122
14209
  line,
14123
14210
  snippet: snippet(file.content, line)
14124
14211
  }
14125
14212
  });
14126
14213
  };
14127
- walk5(tree.rootNode, (node) => {
14214
+ walk6(tree.rootNode, (node) => {
14128
14215
  if (node.type !== "call") return;
14129
14216
  const method = blockCallMethod(node);
14130
14217
  if (method === "add_foreign_key") {
@@ -14185,23 +14272,23 @@ function modelTable(cls) {
14185
14272
  return tableize(nameNode.text);
14186
14273
  }
14187
14274
  function railsModelEndpointsFromFile(file, serviceDir) {
14188
- const tree = parseSource8(makeRubyParser2(), file.content);
14275
+ const tree = parseSource9(makeRubyParser2(), file.content);
14189
14276
  const out = [];
14190
14277
  const seen = /* @__PURE__ */ new Set();
14191
- walk5(tree.rootNode, (node) => {
14278
+ walk6(tree.rootNode, (node) => {
14192
14279
  if (node.type !== "class" || !isActiveRecordModel(node)) return;
14193
14280
  const table = modelTable(node);
14194
14281
  if (!table || seen.has(table)) return;
14195
14282
  seen.add(table);
14196
14283
  const line = node.startPosition.row + 1;
14197
14284
  out.push({
14198
- infraId: (0, import_types40.infraId)("sql-table", table),
14285
+ infraId: (0, import_types41.infraId)("sql-table", table),
14199
14286
  name: table,
14200
14287
  kind: "sql-table",
14201
14288
  edgeType: "CALLS",
14202
14289
  confidenceKind: "verified-call-site",
14203
14290
  evidence: {
14204
- file: import_node_path52.default.relative(serviceDir, file.path),
14291
+ file: import_node_path53.default.relative(serviceDir, file.path),
14205
14292
  line,
14206
14293
  snippet: snippet(file.content, line)
14207
14294
  }
@@ -14211,10 +14298,10 @@ function railsModelEndpointsFromFile(file, serviceDir) {
14211
14298
  }
14212
14299
  var AR_ASSOCIATIONS = /* @__PURE__ */ new Set(["belongs_to", "has_many", "has_one"]);
14213
14300
  function railsModelForeignKeys(file, serviceDir) {
14214
- const tree = parseSource8(makeRubyParser2(), file.content);
14301
+ const tree = parseSource9(makeRubyParser2(), file.content);
14215
14302
  const out = [];
14216
14303
  const seen = /* @__PURE__ */ new Set();
14217
- walk5(tree.rootNode, (node) => {
14304
+ walk6(tree.rootNode, (node) => {
14218
14305
  if (node.type !== "class" || !isActiveRecordModel(node)) return;
14219
14306
  const thisTable = modelTable(node);
14220
14307
  if (!thisTable) return;
@@ -14238,7 +14325,7 @@ function railsModelForeignKeys(file, serviceDir) {
14238
14325
  childTable,
14239
14326
  parentTable,
14240
14327
  evidence: {
14241
- file: import_node_path52.default.relative(serviceDir, file.path),
14328
+ file: import_node_path53.default.relative(serviceDir, file.path),
14242
14329
  line,
14243
14330
  snippet: snippet(file.content, line)
14244
14331
  }
@@ -14250,27 +14337,27 @@ function railsModelForeignKeys(file, serviceDir) {
14250
14337
 
14251
14338
  // src/extract/calls/eloquent.ts
14252
14339
  init_cjs_shims();
14253
- var import_node_path53 = __toESM(require("path"), 1);
14254
- var import_tree_sitter13 = __toESM(require("tree-sitter"), 1);
14340
+ var import_node_path54 = __toESM(require("path"), 1);
14341
+ var import_tree_sitter14 = __toESM(require("tree-sitter"), 1);
14255
14342
  var import_tree_sitter_php3 = __toESM(require("tree-sitter-php"), 1);
14256
- var import_types41 = require("@neat.is/types");
14343
+ var import_types42 = require("@neat.is/types");
14257
14344
  var LARAVEL_SCHEMA_RE = /\bSchema::(create|createIfNotExists|table)\b/;
14258
- var PARSE_CHUNK9 = 16384;
14345
+ var PARSE_CHUNK10 = 16384;
14259
14346
  function makePhpParser2() {
14260
- const p = new import_tree_sitter13.default();
14347
+ const p = new import_tree_sitter14.default();
14261
14348
  p.setLanguage(import_tree_sitter_php3.default.php_only);
14262
14349
  return p;
14263
14350
  }
14264
- function parseSource9(parser, source) {
14351
+ function parseSource10(parser, source) {
14265
14352
  return parser.parse(
14266
- (index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK9)
14353
+ (index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK10)
14267
14354
  );
14268
14355
  }
14269
- function walk6(node, visit) {
14356
+ function walk7(node, visit) {
14270
14357
  visit(node);
14271
14358
  for (let i = 0; i < node.namedChildCount; i++) {
14272
14359
  const c = node.namedChild(i);
14273
- if (c) walk6(c, visit);
14360
+ if (c) walk7(c, visit);
14274
14361
  }
14275
14362
  }
14276
14363
  function phpStaticString2(node) {
@@ -14481,9 +14568,9 @@ function columnsFromCall(chain, blueprintVar) {
14481
14568
  }
14482
14569
  function laravelMigrationEndpointsFromFile(file, serviceDir) {
14483
14570
  if (!LARAVEL_SCHEMA_RE.test(file.content)) return [];
14484
- const tree = parseSource9(makePhpParser2(), file.content);
14571
+ const tree = parseSource10(makePhpParser2(), file.content);
14485
14572
  const out = [];
14486
- walk6(tree.rootNode, (node) => {
14573
+ walk7(tree.rootNode, (node) => {
14487
14574
  if (!isSchemaCall(node)) return;
14488
14575
  const bp = readBlueprint(node);
14489
14576
  if (!bp) return;
@@ -14500,14 +14587,14 @@ function laravelMigrationEndpointsFromFile(file, serviceDir) {
14500
14587
  }
14501
14588
  }
14502
14589
  out.push({
14503
- infraId: (0, import_types41.infraId)("sql-table", bp.table),
14590
+ infraId: (0, import_types42.infraId)("sql-table", bp.table),
14504
14591
  name: bp.table,
14505
14592
  kind: "sql-table",
14506
14593
  edgeType: "CALLS",
14507
14594
  confidenceKind: "structural",
14508
14595
  ...columns.length > 0 ? { columns } : {},
14509
14596
  evidence: {
14510
- file: import_node_path53.default.relative(serviceDir, file.path),
14597
+ file: import_node_path54.default.relative(serviceDir, file.path),
14511
14598
  line: bp.line,
14512
14599
  snippet: snippet(file.content, bp.line)
14513
14600
  }
@@ -14517,7 +14604,7 @@ function laravelMigrationEndpointsFromFile(file, serviceDir) {
14517
14604
  }
14518
14605
  function laravelMigrationForeignKeys(file, serviceDir) {
14519
14606
  if (!LARAVEL_SCHEMA_RE.test(file.content)) return [];
14520
- const tree = parseSource9(makePhpParser2(), file.content);
14607
+ const tree = parseSource10(makePhpParser2(), file.content);
14521
14608
  const out = [];
14522
14609
  const seen = /* @__PURE__ */ new Set();
14523
14610
  const emit = (childTable, parentTable, line) => {
@@ -14529,13 +14616,13 @@ function laravelMigrationForeignKeys(file, serviceDir) {
14529
14616
  childTable,
14530
14617
  parentTable,
14531
14618
  evidence: {
14532
- file: import_node_path53.default.relative(serviceDir, file.path),
14619
+ file: import_node_path54.default.relative(serviceDir, file.path),
14533
14620
  line,
14534
14621
  snippet: snippet(file.content, line)
14535
14622
  }
14536
14623
  });
14537
14624
  };
14538
- walk6(tree.rootNode, (node) => {
14625
+ walk7(tree.rootNode, (node) => {
14539
14626
  if (!isSchemaCall(node)) return;
14540
14627
  const bp = readBlueprint(node);
14541
14628
  if (!bp || !bp.closureBody) return;
@@ -14633,23 +14720,23 @@ function walkWithinClass(cls, visit) {
14633
14720
  recur(body);
14634
14721
  }
14635
14722
  function laravelModelEndpointsFromFile(file, serviceDir) {
14636
- const tree = parseSource9(makePhpParser2(), file.content);
14723
+ const tree = parseSource10(makePhpParser2(), file.content);
14637
14724
  const out = [];
14638
14725
  const seen = /* @__PURE__ */ new Set();
14639
- walk6(tree.rootNode, (node) => {
14726
+ walk7(tree.rootNode, (node) => {
14640
14727
  if (node.type !== "class_declaration" || !isEloquentModel(node)) return;
14641
14728
  const table = modelTable2(node);
14642
14729
  if (!table || seen.has(table)) return;
14643
14730
  seen.add(table);
14644
14731
  const line = node.startPosition.row + 1;
14645
14732
  out.push({
14646
- infraId: (0, import_types41.infraId)("sql-table", table),
14733
+ infraId: (0, import_types42.infraId)("sql-table", table),
14647
14734
  name: table,
14648
14735
  kind: "sql-table",
14649
14736
  edgeType: "CALLS",
14650
14737
  confidenceKind: "verified-call-site",
14651
14738
  evidence: {
14652
- file: import_node_path53.default.relative(serviceDir, file.path),
14739
+ file: import_node_path54.default.relative(serviceDir, file.path),
14653
14740
  line,
14654
14741
  snippet: snippet(file.content, line)
14655
14742
  }
@@ -14659,10 +14746,10 @@ function laravelModelEndpointsFromFile(file, serviceDir) {
14659
14746
  }
14660
14747
  var ELOQUENT_RELATIONS = /* @__PURE__ */ new Set(["belongsTo", "hasMany", "hasOne"]);
14661
14748
  function laravelModelForeignKeys(file, serviceDir) {
14662
- const tree = parseSource9(makePhpParser2(), file.content);
14749
+ const tree = parseSource10(makePhpParser2(), file.content);
14663
14750
  const out = [];
14664
14751
  const seen = /* @__PURE__ */ new Set();
14665
- walk6(tree.rootNode, (node) => {
14752
+ walk7(tree.rootNode, (node) => {
14666
14753
  if (node.type !== "class_declaration" || !isEloquentModel(node)) return;
14667
14754
  const thisTable = modelTable2(node);
14668
14755
  if (!thisTable) return;
@@ -14685,7 +14772,7 @@ function laravelModelForeignKeys(file, serviceDir) {
14685
14772
  childTable,
14686
14773
  parentTable,
14687
14774
  evidence: {
14688
- file: import_node_path53.default.relative(serviceDir, file.path),
14775
+ file: import_node_path54.default.relative(serviceDir, file.path),
14689
14776
  line,
14690
14777
  snippet: snippet(file.content, line)
14691
14778
  }
@@ -14697,12 +14784,12 @@ function laravelModelForeignKeys(file, serviceDir) {
14697
14784
 
14698
14785
  // src/extract/calls/go.ts
14699
14786
  init_cjs_shims();
14700
- var import_node_path56 = __toESM(require("path"), 1);
14701
- var import_tree_sitter14 = __toESM(require("tree-sitter"), 1);
14787
+ var import_node_path57 = __toESM(require("path"), 1);
14788
+ var import_tree_sitter15 = __toESM(require("tree-sitter"), 1);
14702
14789
  var import_tree_sitter_go4 = __toESM(require("tree-sitter-go"), 1);
14703
- var import_types42 = require("@neat.is/types");
14790
+ var import_types43 = require("@neat.is/types");
14704
14791
  init_otel();
14705
- var PARSE_CHUNK10 = 16384;
14792
+ var PARSE_CHUNK11 = 16384;
14706
14793
  var DATABASE_SQL_METHODS = /* @__PURE__ */ new Set([
14707
14794
  "Query",
14708
14795
  "QueryContext",
@@ -14728,20 +14815,20 @@ var SQLX_METHODS = /* @__PURE__ */ new Set([
14728
14815
  var DATABASE_SQL_IMPORT = "database/sql";
14729
14816
  var SQLX_IMPORT = "github.com/jmoiron/sqlx";
14730
14817
  function makeGoParser3() {
14731
- const p = new import_tree_sitter14.default();
14818
+ const p = new import_tree_sitter15.default();
14732
14819
  p.setLanguage(import_tree_sitter_go4.default);
14733
14820
  return p;
14734
14821
  }
14735
- function parseSource10(parser, source) {
14822
+ function parseSource11(parser, source) {
14736
14823
  return parser.parse(
14737
- (index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK10)
14824
+ (index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK11)
14738
14825
  );
14739
14826
  }
14740
- function walk7(node, visit) {
14827
+ function walk8(node, visit) {
14741
14828
  visit(node);
14742
14829
  for (let i = 0; i < node.namedChildCount; i++) {
14743
14830
  const child = node.namedChild(i);
14744
- if (child) walk7(child, visit);
14831
+ if (child) walk8(child, visit);
14745
14832
  }
14746
14833
  }
14747
14834
  function goStringLiteralValue(node) {
@@ -14754,7 +14841,7 @@ function goStringLiteralValue(node) {
14754
14841
  }
14755
14842
  function goImportsAny(root, names) {
14756
14843
  let found = false;
14757
- walk7(root, (node) => {
14844
+ walk8(root, (node) => {
14758
14845
  if (found || node.type !== "import_spec") return;
14759
14846
  for (let i = 0; i < node.namedChildCount; i++) {
14760
14847
  const value = goStringLiteralValue(node.namedChild(i));
@@ -14772,14 +14859,14 @@ function firstStringLiteralArg(argsNode) {
14772
14859
  return null;
14773
14860
  }
14774
14861
  function goSqlEndpointsFromFile(file, serviceDir) {
14775
- if (import_node_path56.default.extname(file.path) !== ".go") return [];
14862
+ if (import_node_path57.default.extname(file.path) !== ".go") return [];
14776
14863
  if (!file.content.includes(DATABASE_SQL_IMPORT) && !file.content.includes(SQLX_IMPORT)) return [];
14777
- const tree = parseSource10(makeGoParser3(), file.content);
14864
+ const tree = parseSource11(makeGoParser3(), file.content);
14778
14865
  const importsDatabaseSql = goImportsAny(tree.rootNode, /* @__PURE__ */ new Set([DATABASE_SQL_IMPORT]));
14779
14866
  const importsSqlx = goImportsAny(tree.rootNode, /* @__PURE__ */ new Set([SQLX_IMPORT]));
14780
14867
  if (!importsDatabaseSql && !importsSqlx) return [];
14781
14868
  const out = [];
14782
- walk7(tree.rootNode, (node) => {
14869
+ walk8(tree.rootNode, (node) => {
14783
14870
  if (node.type !== "call_expression") return;
14784
14871
  const fn = node.childForFieldName("function");
14785
14872
  if (fn?.type !== "selector_expression") return;
@@ -14794,14 +14881,14 @@ function goSqlEndpointsFromFile(file, serviceDir) {
14794
14881
  const columns = columnsFromSqlStatement(sql);
14795
14882
  const line = node.startPosition.row + 1;
14796
14883
  out.push({
14797
- infraId: (0, import_types42.infraId)("sql-table", table),
14884
+ infraId: (0, import_types43.infraId)("sql-table", table),
14798
14885
  name: table,
14799
14886
  kind: "sql-table",
14800
14887
  edgeType: "CALLS",
14801
14888
  confidenceKind: "verified-call-site",
14802
14889
  ...columns.length > 0 ? { columns } : {},
14803
14890
  evidence: {
14804
- file: toPosix(import_node_path56.default.relative(serviceDir, file.path)),
14891
+ file: toPosix(import_node_path57.default.relative(serviceDir, file.path)),
14805
14892
  line,
14806
14893
  snippet: snippet(file.content, line)
14807
14894
  }
@@ -14812,27 +14899,27 @@ function goSqlEndpointsFromFile(file, serviceDir) {
14812
14899
 
14813
14900
  // src/extract/calls/gorm.ts
14814
14901
  init_cjs_shims();
14815
- var import_node_path57 = __toESM(require("path"), 1);
14816
- var import_tree_sitter15 = __toESM(require("tree-sitter"), 1);
14902
+ var import_node_path58 = __toESM(require("path"), 1);
14903
+ var import_tree_sitter16 = __toESM(require("tree-sitter"), 1);
14817
14904
  var import_tree_sitter_go5 = __toESM(require("tree-sitter-go"), 1);
14818
- var import_types43 = require("@neat.is/types");
14905
+ var import_types44 = require("@neat.is/types");
14819
14906
  var GORM_IMPORT_RE = /gorm\.io\/gorm/;
14820
- var PARSE_CHUNK11 = 16384;
14907
+ var PARSE_CHUNK12 = 16384;
14821
14908
  function makeGoParser4() {
14822
- const p = new import_tree_sitter15.default();
14909
+ const p = new import_tree_sitter16.default();
14823
14910
  p.setLanguage(import_tree_sitter_go5.default);
14824
14911
  return p;
14825
14912
  }
14826
- function parseSource11(parser, source) {
14913
+ function parseSource12(parser, source) {
14827
14914
  return parser.parse(
14828
- (index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK11)
14915
+ (index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK12)
14829
14916
  );
14830
14917
  }
14831
- function walk8(node, visit) {
14918
+ function walk9(node, visit) {
14832
14919
  visit(node);
14833
14920
  for (let i = 0; i < node.namedChildCount; i++) {
14834
14921
  const c = node.namedChild(i);
14835
- if (c) walk8(c, visit);
14922
+ if (c) walk9(c, visit);
14836
14923
  }
14837
14924
  }
14838
14925
  var COMMON_INITIALISMS = [
@@ -15065,7 +15152,7 @@ function readField(fieldDecl) {
15065
15152
  }
15066
15153
  function collectStructs(tree) {
15067
15154
  const structs = /* @__PURE__ */ new Map();
15068
- walk8(tree.rootNode, (node) => {
15155
+ walk9(tree.rootNode, (node) => {
15069
15156
  if (node.type !== "type_spec") return;
15070
15157
  const nameNode = node.childForFieldName("name");
15071
15158
  const typeNode = node.childForFieldName("type");
@@ -15114,7 +15201,7 @@ function compositeStructName(arg) {
15114
15201
  }
15115
15202
  function collectCallModels(tree) {
15116
15203
  const models = /* @__PURE__ */ new Set();
15117
- walk8(tree.rootNode, (node) => {
15204
+ walk9(tree.rootNode, (node) => {
15118
15205
  if (node.type !== "call_expression") return;
15119
15206
  const fn = node.childForFieldName("function");
15120
15207
  if (fn?.type !== "selector_expression") return;
@@ -15134,7 +15221,7 @@ function collectCallModels(tree) {
15134
15221
  function collectTableNameOverrides(tree) {
15135
15222
  const overrides = /* @__PURE__ */ new Map();
15136
15223
  const declarers = /* @__PURE__ */ new Set();
15137
- walk8(tree.rootNode, (node) => {
15224
+ walk9(tree.rootNode, (node) => {
15138
15225
  if (node.type !== "method_declaration") return;
15139
15226
  if (node.childForFieldName("name")?.text !== "TableName") return;
15140
15227
  const receiver = node.childForFieldName("receiver");
@@ -15151,7 +15238,7 @@ function collectTableNameOverrides(tree) {
15151
15238
  const body = node.childForFieldName("body");
15152
15239
  if (!body) return;
15153
15240
  let literal = null;
15154
- walk8(body, (n) => {
15241
+ walk9(body, (n) => {
15155
15242
  if (literal !== null) return;
15156
15243
  if (n.type !== "return_statement") return;
15157
15244
  const exprList = n.namedChild(0);
@@ -15245,9 +15332,9 @@ function collectColumns(struct, structs, seen, prefix, out, emitted) {
15245
15332
  seen.delete(struct.name);
15246
15333
  }
15247
15334
  function gormEndpointsFromFile(file, serviceDir) {
15248
- if (import_node_path57.default.extname(file.path) !== ".go") return [];
15335
+ if (import_node_path58.default.extname(file.path) !== ".go") return [];
15249
15336
  if (!GORM_IMPORT_RE.test(file.content)) return [];
15250
- const tree = parseSource11(makeGoParser4(), file.content);
15337
+ const tree = parseSource12(makeGoParser4(), file.content);
15251
15338
  const { structs, models, tableFor } = analyze(tree);
15252
15339
  const out = [];
15253
15340
  const seenTables = /* @__PURE__ */ new Set();
@@ -15260,14 +15347,14 @@ function gormEndpointsFromFile(file, serviceDir) {
15260
15347
  const columns = [];
15261
15348
  collectColumns(struct, structs, /* @__PURE__ */ new Set(), "", columns, /* @__PURE__ */ new Set());
15262
15349
  out.push({
15263
- infraId: (0, import_types43.infraId)("sql-table", table),
15350
+ infraId: (0, import_types44.infraId)("sql-table", table),
15264
15351
  name: table,
15265
15352
  kind: "sql-table",
15266
15353
  edgeType: "CALLS",
15267
15354
  confidenceKind: "structural",
15268
15355
  ...columns.length > 0 ? { columns } : {},
15269
15356
  evidence: {
15270
- file: toPosix(import_node_path57.default.relative(serviceDir, file.path)),
15357
+ file: toPosix(import_node_path58.default.relative(serviceDir, file.path)),
15271
15358
  line: struct.line,
15272
15359
  snippet: snippet(file.content, struct.line)
15273
15360
  }
@@ -15276,9 +15363,9 @@ function gormEndpointsFromFile(file, serviceDir) {
15276
15363
  return out;
15277
15364
  }
15278
15365
  function gormForeignKeys(file, serviceDir) {
15279
- if (import_node_path57.default.extname(file.path) !== ".go") return [];
15366
+ if (import_node_path58.default.extname(file.path) !== ".go") return [];
15280
15367
  if (!GORM_IMPORT_RE.test(file.content)) return [];
15281
- const tree = parseSource11(makeGoParser4(), file.content);
15368
+ const tree = parseSource12(makeGoParser4(), file.content);
15282
15369
  const { structs, models, tableFor } = analyze(tree);
15283
15370
  const out = [];
15284
15371
  const seen = /* @__PURE__ */ new Set();
@@ -15291,7 +15378,7 @@ function gormForeignKeys(file, serviceDir) {
15291
15378
  childTable,
15292
15379
  parentTable,
15293
15380
  evidence: {
15294
- file: toPosix(import_node_path57.default.relative(serviceDir, file.path)),
15381
+ file: toPosix(import_node_path58.default.relative(serviceDir, file.path)),
15295
15382
  line,
15296
15383
  snippet: snippet(file.content, line)
15297
15384
  }
@@ -15328,27 +15415,27 @@ function gormForeignKeys(file, serviceDir) {
15328
15415
 
15329
15416
  // src/extract/calls/efcore.ts
15330
15417
  init_cjs_shims();
15331
- var import_node_path58 = __toESM(require("path"), 1);
15332
- var import_tree_sitter16 = __toESM(require("tree-sitter"), 1);
15418
+ var import_node_path59 = __toESM(require("path"), 1);
15419
+ var import_tree_sitter17 = __toESM(require("tree-sitter"), 1);
15333
15420
  var import_tree_sitter_c_sharp2 = __toESM(require("tree-sitter-c-sharp"), 1);
15334
- var import_types44 = require("@neat.is/types");
15421
+ var import_types45 = require("@neat.is/types");
15335
15422
  var EFCORE_GATE = /Microsoft\.EntityFrameworkCore|DataAnnotations\.Schema|\bDbContext\b|\bDbSet\s*</;
15336
- var PARSE_CHUNK12 = 16384;
15423
+ var PARSE_CHUNK13 = 16384;
15337
15424
  function makeCsParser() {
15338
- const p = new import_tree_sitter16.default();
15425
+ const p = new import_tree_sitter17.default();
15339
15426
  p.setLanguage(import_tree_sitter_c_sharp2.default);
15340
15427
  return p;
15341
15428
  }
15342
- function parseSource12(parser, source) {
15429
+ function parseSource13(parser, source) {
15343
15430
  return parser.parse(
15344
- (index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK12)
15431
+ (index) => index >= source.length ? "" : source.slice(index, index + PARSE_CHUNK13)
15345
15432
  );
15346
15433
  }
15347
- function walk9(node, visit) {
15434
+ function walk10(node, visit) {
15348
15435
  visit(node);
15349
15436
  for (let i = 0; i < node.namedChildCount; i++) {
15350
15437
  const c = node.namedChild(i);
15351
- if (c) walk9(c, visit);
15438
+ if (c) walk10(c, visit);
15352
15439
  }
15353
15440
  }
15354
15441
  function firstChildOfType(node, type) {
@@ -15407,28 +15494,28 @@ function tableFromToTable(call) {
15407
15494
  return value ? csStringLiteral(value) : null;
15408
15495
  }
15409
15496
  function efcoreEndpointsFromFile(file, serviceDir) {
15410
- if (import_node_path58.default.extname(file.path) !== ".cs") return [];
15497
+ if (import_node_path59.default.extname(file.path) !== ".cs") return [];
15411
15498
  if (!EFCORE_GATE.test(file.content)) return [];
15412
- const tree = parseSource12(makeCsParser(), file.content);
15499
+ const tree = parseSource13(makeCsParser(), file.content);
15413
15500
  const out = [];
15414
15501
  const seen = /* @__PURE__ */ new Set();
15415
15502
  const push = (name, line) => {
15416
15503
  if (!name || seen.has(name)) return;
15417
15504
  seen.add(name);
15418
15505
  out.push({
15419
- infraId: (0, import_types44.infraId)("sql-table", name),
15506
+ infraId: (0, import_types45.infraId)("sql-table", name),
15420
15507
  name,
15421
15508
  kind: "sql-table",
15422
15509
  edgeType: "CALLS",
15423
15510
  confidenceKind: "structural",
15424
15511
  evidence: {
15425
- file: toPosix(import_node_path58.default.relative(serviceDir, file.path)),
15512
+ file: toPosix(import_node_path59.default.relative(serviceDir, file.path)),
15426
15513
  line,
15427
15514
  snippet: snippet(file.content, line)
15428
15515
  }
15429
15516
  });
15430
15517
  };
15431
- walk9(tree.rootNode, (node) => {
15518
+ walk10(tree.rootNode, (node) => {
15432
15519
  if (node.type === "attribute") {
15433
15520
  const table = tableFromAttribute(node);
15434
15521
  if (table) push(table, node.startPosition.row + 1);
@@ -15446,11 +15533,11 @@ function efcoreEndpointsFromFile(file, serviceDir) {
15446
15533
  function edgeTypeFromEndpoint(ep) {
15447
15534
  switch (ep.edgeType) {
15448
15535
  case "PUBLISHES_TO":
15449
- return import_types45.EdgeType.PUBLISHES_TO;
15536
+ return import_types46.EdgeType.PUBLISHES_TO;
15450
15537
  case "CONSUMES_FROM":
15451
- return import_types45.EdgeType.CONSUMES_FROM;
15538
+ return import_types46.EdgeType.CONSUMES_FROM;
15452
15539
  default:
15453
- return import_types45.EdgeType.CALLS;
15540
+ return import_types46.EdgeType.CALLS;
15454
15541
  }
15455
15542
  }
15456
15543
  function isAwsKind(kind) {
@@ -15505,6 +15592,11 @@ async function addExternalEndpointEdges(graph, services) {
15505
15592
  } catch (err) {
15506
15593
  recordExtractionError("efcore data-axis extraction", file.path, err);
15507
15594
  }
15595
+ try {
15596
+ endpoints.push(...socketEndpointsFromFile(file, service.dir));
15597
+ } catch (err) {
15598
+ recordExtractionError("python socket call extraction", file.path, err);
15599
+ }
15508
15600
  }
15509
15601
  endpoints.push(...await mongooseCrossFileEndpoints(maskedFiles, service.dir));
15510
15602
  endpoints.push(...pythonOrmCrossFileEndpoints(maskedFiles, service.dir));
@@ -15515,7 +15607,7 @@ async function addExternalEndpointEdges(graph, services) {
15515
15607
  if (!graph.hasNode(ep.infraId)) {
15516
15608
  const node = {
15517
15609
  id: ep.infraId,
15518
- type: import_types45.NodeType.InfraNode,
15610
+ type: import_types46.NodeType.InfraNode,
15519
15611
  name: ep.name,
15520
15612
  // #238 — `aws-*` covers AWS-SDK client kinds (aws-s3, aws-dynamodb,
15521
15613
  // aws-cognito-identity-provider, …); `s3-` / `dynamodb-` cover the
@@ -15528,21 +15620,21 @@ async function addExternalEndpointEdges(graph, services) {
15528
15620
  }
15529
15621
  if (ep.columns && ep.columns.length > 0) {
15530
15622
  const node = graph.getNodeAttributes(ep.infraId);
15531
- if (node.type === import_types45.NodeType.InfraNode) {
15623
+ if (node.type === import_types46.NodeType.InfraNode) {
15532
15624
  graph.replaceNodeAttributes(ep.infraId, {
15533
15625
  ...node,
15534
15626
  columns: foldColumns(
15535
15627
  node.columns,
15536
15628
  ep.columns,
15537
- import_types45.Provenance.EXTRACTED,
15538
- (0, import_types45.confidenceForExtracted)(ep.confidenceKind)
15629
+ import_types46.Provenance.EXTRACTED,
15630
+ (0, import_types46.confidenceForExtracted)(ep.confidenceKind)
15539
15631
  )
15540
15632
  });
15541
15633
  }
15542
15634
  }
15543
15635
  if (ep.sdkWrites && Object.keys(ep.sdkWrites).length > 0) {
15544
15636
  const node = graph.getNodeAttributes(ep.infraId);
15545
- if (node.type === import_types45.NodeType.InfraNode) {
15637
+ if (node.type === import_types46.NodeType.InfraNode) {
15546
15638
  graph.replaceNodeAttributes(ep.infraId, {
15547
15639
  ...node,
15548
15640
  columns: foldSdkWrites(node.columns, ep.sdkWrites)
@@ -15550,7 +15642,7 @@ async function addExternalEndpointEdges(graph, services) {
15550
15642
  }
15551
15643
  }
15552
15644
  const edgeType = edgeTypeFromEndpoint(ep);
15553
- const confidence = (0, import_types45.confidenceForExtracted)(ep.confidenceKind);
15645
+ const confidence = (0, import_types46.confidenceForExtracted)(ep.confidenceKind);
15554
15646
  const relFile = toPosix(ep.evidence.file);
15555
15647
  const { fileNodeId, nodesAdded: n, edgesAdded: e } = ensureFileNode(
15556
15648
  graph,
@@ -15560,7 +15652,7 @@ async function addExternalEndpointEdges(graph, services) {
15560
15652
  );
15561
15653
  nodesAdded += n;
15562
15654
  edgesAdded += e;
15563
- if (!(0, import_types45.passesExtractedFloor)(confidence)) {
15655
+ if (!(0, import_types46.passesExtractedFloor)(confidence)) {
15564
15656
  noteExtractedDropped({
15565
15657
  source: fileNodeId,
15566
15658
  target: ep.infraId,
@@ -15580,7 +15672,7 @@ async function addExternalEndpointEdges(graph, services) {
15580
15672
  source: fileNodeId,
15581
15673
  target: ep.infraId,
15582
15674
  type: edgeType,
15583
- provenance: import_types45.Provenance.EXTRACTED,
15675
+ provenance: import_types46.Provenance.EXTRACTED,
15584
15676
  confidence,
15585
15677
  evidence: ep.evidence
15586
15678
  };
@@ -15603,7 +15695,7 @@ async function addCallEdges(graph, services) {
15603
15695
 
15604
15696
  // src/extract/table-edges.ts
15605
15697
  init_cjs_shims();
15606
- var import_types46 = require("@neat.is/types");
15698
+ var import_types47 = require("@neat.is/types");
15607
15699
  async function addTableEdges(graph, services) {
15608
15700
  let nodesAdded = 0;
15609
15701
  let edgesAdded = 0;
@@ -15631,20 +15723,20 @@ async function addTableEdges(graph, services) {
15631
15723
  }
15632
15724
  refs.push(...modelRefs);
15633
15725
  for (const ref of refs) {
15634
- const childId = (0, import_types46.infraId)("sql-table", ref.childTable);
15635
- const parentId = (0, import_types46.infraId)("sql-table", ref.parentTable);
15726
+ const childId = (0, import_types47.infraId)("sql-table", ref.childTable);
15727
+ const parentId = (0, import_types47.infraId)("sql-table", ref.parentTable);
15636
15728
  if (childId === parentId) continue;
15637
15729
  nodesAdded += ensureTableNode(graph, childId, ref.childTable);
15638
15730
  nodesAdded += ensureTableNode(graph, parentId, ref.parentTable);
15639
- const edgeId = (0, import_types46.extractedEdgeId)(childId, parentId, import_types46.EdgeType.REFERENCES);
15731
+ const edgeId = (0, import_types47.extractedEdgeId)(childId, parentId, import_types47.EdgeType.REFERENCES);
15640
15732
  if (graph.hasEdge(edgeId)) continue;
15641
15733
  const edge = {
15642
15734
  id: edgeId,
15643
15735
  source: childId,
15644
15736
  target: parentId,
15645
- type: import_types46.EdgeType.REFERENCES,
15646
- provenance: import_types46.Provenance.EXTRACTED,
15647
- confidence: (0, import_types46.confidenceForExtracted)("structural"),
15737
+ type: import_types47.EdgeType.REFERENCES,
15738
+ provenance: import_types47.Provenance.EXTRACTED,
15739
+ confidence: (0, import_types47.confidenceForExtracted)("structural"),
15648
15740
  evidence: ref.evidence
15649
15741
  };
15650
15742
  graph.addEdgeWithKey(edgeId, childId, parentId, edge);
@@ -15657,7 +15749,7 @@ function ensureTableNode(graph, id, name) {
15657
15749
  if (graph.hasNode(id)) return 0;
15658
15750
  const node = {
15659
15751
  id,
15660
- type: import_types46.NodeType.InfraNode,
15752
+ type: import_types47.NodeType.InfraNode,
15661
15753
  name,
15662
15754
  provider: "self",
15663
15755
  kind: "sql-table"
@@ -15671,16 +15763,16 @@ init_cjs_shims();
15671
15763
 
15672
15764
  // src/extract/infra/docker-compose.ts
15673
15765
  init_cjs_shims();
15674
- var import_node_path59 = __toESM(require("path"), 1);
15675
- var import_types48 = require("@neat.is/types");
15766
+ var import_node_path60 = __toESM(require("path"), 1);
15767
+ var import_types49 = require("@neat.is/types");
15676
15768
 
15677
15769
  // src/extract/infra/shared.ts
15678
15770
  init_cjs_shims();
15679
- var import_types47 = require("@neat.is/types");
15771
+ var import_types48 = require("@neat.is/types");
15680
15772
  function makeInfraNode(kind, name, provider = "self", extras) {
15681
15773
  return {
15682
- id: (0, import_types47.infraId)(kind, name),
15683
- type: import_types47.NodeType.InfraNode,
15774
+ id: (0, import_types48.infraId)(kind, name),
15775
+ type: import_types48.NodeType.InfraNode,
15684
15776
  name,
15685
15777
  provider,
15686
15778
  kind,
@@ -15724,8 +15816,8 @@ function emitPlatformResourceEdge(graph, anchorId, edgeType, kind, name, provide
15724
15816
  source: anchorId,
15725
15817
  target: node.id,
15726
15818
  type: edgeType,
15727
- provenance: import_types47.Provenance.EXTRACTED,
15728
- confidence: (0, import_types47.confidenceForExtracted)("structural"),
15819
+ provenance: import_types48.Provenance.EXTRACTED,
15820
+ confidence: (0, import_types48.confidenceForExtracted)("structural"),
15729
15821
  evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
15730
15822
  };
15731
15823
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -15742,7 +15834,7 @@ function dependsOnList(value) {
15742
15834
  }
15743
15835
  function serviceNameToServiceNode(name, services) {
15744
15836
  for (const s of services) {
15745
- if (s.node.name === name || import_node_path59.default.basename(s.dir) === name) return s.node.id;
15837
+ if (s.node.name === name || import_node_path60.default.basename(s.dir) === name) return s.node.id;
15746
15838
  }
15747
15839
  return null;
15748
15840
  }
@@ -15751,7 +15843,7 @@ async function addComposeInfra(graph, scanPath, services) {
15751
15843
  let edgesAdded = 0;
15752
15844
  let composePath = null;
15753
15845
  for (const name of ["docker-compose.yml", "docker-compose.yaml"]) {
15754
- const abs = import_node_path59.default.join(scanPath, name);
15846
+ const abs = import_node_path60.default.join(scanPath, name);
15755
15847
  if (await exists2(abs)) {
15756
15848
  composePath = abs;
15757
15849
  break;
@@ -15764,13 +15856,13 @@ async function addComposeInfra(graph, scanPath, services) {
15764
15856
  } catch (err) {
15765
15857
  recordExtractionError(
15766
15858
  "infra docker-compose",
15767
- import_node_path59.default.relative(scanPath, composePath),
15859
+ import_node_path60.default.relative(scanPath, composePath),
15768
15860
  err
15769
15861
  );
15770
15862
  return { nodesAdded, edgesAdded };
15771
15863
  }
15772
15864
  if (!compose?.services) return { nodesAdded, edgesAdded };
15773
- const evidenceFile = import_node_path59.default.relative(scanPath, composePath).split(import_node_path59.default.sep).join("/");
15865
+ const evidenceFile = import_node_path60.default.relative(scanPath, composePath).split(import_node_path60.default.sep).join("/");
15774
15866
  const composeNameToNodeId = /* @__PURE__ */ new Map();
15775
15867
  for (const [composeName, svc] of Object.entries(compose.services)) {
15776
15868
  const matchedServiceId = serviceNameToServiceNode(composeName, services);
@@ -15792,15 +15884,15 @@ async function addComposeInfra(graph, scanPath, services) {
15792
15884
  for (const dep of dependsOnList(svc.depends_on)) {
15793
15885
  const targetId = composeNameToNodeId.get(dep);
15794
15886
  if (!targetId) continue;
15795
- const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId, import_types48.EdgeType.DEPENDS_ON);
15887
+ const edgeId = (0, import_types3.extractedEdgeId)(sourceId, targetId, import_types49.EdgeType.DEPENDS_ON);
15796
15888
  if (graph.hasEdge(edgeId)) continue;
15797
15889
  const edge = {
15798
15890
  id: edgeId,
15799
15891
  source: sourceId,
15800
15892
  target: targetId,
15801
- type: import_types48.EdgeType.DEPENDS_ON,
15802
- provenance: import_types48.Provenance.EXTRACTED,
15803
- confidence: (0, import_types48.confidenceForExtracted)("structural"),
15893
+ type: import_types49.EdgeType.DEPENDS_ON,
15894
+ provenance: import_types49.Provenance.EXTRACTED,
15895
+ confidence: (0, import_types49.confidenceForExtracted)("structural"),
15804
15896
  evidence: { file: evidenceFile }
15805
15897
  };
15806
15898
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -15812,9 +15904,9 @@ async function addComposeInfra(graph, scanPath, services) {
15812
15904
 
15813
15905
  // src/extract/infra/dockerfile.ts
15814
15906
  init_cjs_shims();
15815
- var import_node_path60 = __toESM(require("path"), 1);
15907
+ var import_node_path61 = __toESM(require("path"), 1);
15816
15908
  var import_node_fs27 = require("fs");
15817
- var import_types49 = require("@neat.is/types");
15909
+ var import_types50 = require("@neat.is/types");
15818
15910
  function readDockerfile(content) {
15819
15911
  let image = null;
15820
15912
  const ports = [];
@@ -15843,7 +15935,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
15843
15935
  let nodesAdded = 0;
15844
15936
  let edgesAdded = 0;
15845
15937
  for (const service of services) {
15846
- const dockerfilePath = import_node_path60.default.join(service.dir, "Dockerfile");
15938
+ const dockerfilePath = import_node_path61.default.join(service.dir, "Dockerfile");
15847
15939
  if (!await exists2(dockerfilePath)) continue;
15848
15940
  let content;
15849
15941
  try {
@@ -15851,7 +15943,7 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
15851
15943
  } catch (err) {
15852
15944
  recordExtractionError(
15853
15945
  "infra dockerfile",
15854
- import_node_path60.default.relative(scanPath, dockerfilePath),
15946
+ import_node_path61.default.relative(scanPath, dockerfilePath),
15855
15947
  err
15856
15948
  );
15857
15949
  continue;
@@ -15863,8 +15955,8 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
15863
15955
  graph.addNode(node.id, node);
15864
15956
  nodesAdded++;
15865
15957
  }
15866
- const relDockerfile = toPosix(import_node_path60.default.relative(service.dir, dockerfilePath));
15867
- const evidenceFile = toPosix(import_node_path60.default.relative(scanPath, dockerfilePath));
15958
+ const relDockerfile = toPosix(import_node_path61.default.relative(service.dir, dockerfilePath));
15959
+ const evidenceFile = toPosix(import_node_path61.default.relative(scanPath, dockerfilePath));
15868
15960
  const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
15869
15961
  graph,
15870
15962
  service.pkg.name,
@@ -15873,15 +15965,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
15873
15965
  );
15874
15966
  nodesAdded += fn;
15875
15967
  edgesAdded += fe;
15876
- const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types49.EdgeType.RUNS_ON);
15968
+ const edgeId = (0, import_types3.extractedEdgeId)(fileNodeId, node.id, import_types50.EdgeType.RUNS_ON);
15877
15969
  if (!graph.hasEdge(edgeId)) {
15878
15970
  const edge = {
15879
15971
  id: edgeId,
15880
15972
  source: fileNodeId,
15881
15973
  target: node.id,
15882
- type: import_types49.EdgeType.RUNS_ON,
15883
- provenance: import_types49.Provenance.EXTRACTED,
15884
- confidence: (0, import_types49.confidenceForExtracted)("structural"),
15974
+ type: import_types50.EdgeType.RUNS_ON,
15975
+ provenance: import_types50.Provenance.EXTRACTED,
15976
+ confidence: (0, import_types50.confidenceForExtracted)("structural"),
15885
15977
  evidence: {
15886
15978
  file: evidenceFile,
15887
15979
  ...facts.entrypoint ? { snippet: facts.entrypoint.slice(0, 120) } : {}
@@ -15896,15 +15988,15 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
15896
15988
  graph.addNode(portNode.id, portNode);
15897
15989
  nodesAdded++;
15898
15990
  }
15899
- const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id, import_types49.EdgeType.CONNECTS_TO);
15991
+ const portEdgeId = (0, import_types3.extractedEdgeId)(fileNodeId, portNode.id, import_types50.EdgeType.CONNECTS_TO);
15900
15992
  if (graph.hasEdge(portEdgeId)) continue;
15901
15993
  const portEdge = {
15902
15994
  id: portEdgeId,
15903
15995
  source: fileNodeId,
15904
15996
  target: portNode.id,
15905
- type: import_types49.EdgeType.CONNECTS_TO,
15906
- provenance: import_types49.Provenance.EXTRACTED,
15907
- confidence: (0, import_types49.confidenceForExtracted)("structural"),
15997
+ type: import_types50.EdgeType.CONNECTS_TO,
15998
+ provenance: import_types50.Provenance.EXTRACTED,
15999
+ confidence: (0, import_types50.confidenceForExtracted)("structural"),
15908
16000
  evidence: { file: evidenceFile, snippet: `EXPOSE ${port}` }
15909
16001
  };
15910
16002
  graph.addEdgeWithKey(portEdgeId, portEdge.source, portEdge.target, portEdge);
@@ -15917,8 +16009,8 @@ async function addDockerfileRuntimes(graph, services, scanPath) {
15917
16009
  // src/extract/infra/terraform.ts
15918
16010
  init_cjs_shims();
15919
16011
  var import_node_fs28 = require("fs");
15920
- var import_node_path61 = __toESM(require("path"), 1);
15921
- var import_types50 = require("@neat.is/types");
16012
+ var import_node_path62 = __toESM(require("path"), 1);
16013
+ var import_types51 = require("@neat.is/types");
15922
16014
  var RESOURCE_RE = /resource\s+"(aws_[A-Za-z0-9_]+)"\s+"([A-Za-z0-9_-]+)"/g;
15923
16015
  var REFERENCE_RE = /(?<![\w.])(aws_[A-Za-z0-9_]+)\.([A-Za-z0-9_-]+)/g;
15924
16016
  async function walkTfFiles(start, depth = 0, max = 5) {
@@ -15928,11 +16020,11 @@ async function walkTfFiles(start, depth = 0, max = 5) {
15928
16020
  for (const entry of entries) {
15929
16021
  if (entry.isDirectory()) {
15930
16022
  if (IGNORED_DIRS.has(entry.name) || entry.name === ".terraform") continue;
15931
- const child = import_node_path61.default.join(start, entry.name);
16023
+ const child = import_node_path62.default.join(start, entry.name);
15932
16024
  if (await isPythonVenvDir(child)) continue;
15933
16025
  out.push(...await walkTfFiles(child, depth + 1, max));
15934
16026
  } else if (entry.isFile() && entry.name.endsWith(".tf")) {
15935
- out.push(import_node_path61.default.join(start, entry.name));
16027
+ out.push(import_node_path62.default.join(start, entry.name));
15936
16028
  }
15937
16029
  }
15938
16030
  return out;
@@ -15964,7 +16056,7 @@ async function addTerraformResources(graph, scanPath) {
15964
16056
  const files = await walkTfFiles(scanPath);
15965
16057
  for (const file of files) {
15966
16058
  const content = await import_node_fs28.promises.readFile(file, "utf8");
15967
- const evidenceFile = toPosix(import_node_path61.default.relative(scanPath, file));
16059
+ const evidenceFile = toPosix(import_node_path62.default.relative(scanPath, file));
15968
16060
  const resources = [];
15969
16061
  const byKey = /* @__PURE__ */ new Map();
15970
16062
  RESOURCE_RE.lastIndex = 0;
@@ -15999,16 +16091,16 @@ async function addTerraformResources(graph, scanPath) {
15999
16091
  if (!target) continue;
16000
16092
  if (seen.has(target.nodeId)) continue;
16001
16093
  seen.add(target.nodeId);
16002
- const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId, import_types50.EdgeType.DEPENDS_ON);
16094
+ const edgeId = (0, import_types3.extractedEdgeId)(resource.nodeId, target.nodeId, import_types51.EdgeType.DEPENDS_ON);
16003
16095
  if (graph.hasEdge(edgeId)) continue;
16004
16096
  const line = lineAt2(content, resource.bodyOffset + ref.index);
16005
16097
  const edge = {
16006
16098
  id: edgeId,
16007
16099
  source: resource.nodeId,
16008
16100
  target: target.nodeId,
16009
- type: import_types50.EdgeType.DEPENDS_ON,
16010
- provenance: import_types50.Provenance.EXTRACTED,
16011
- confidence: (0, import_types50.confidenceForExtracted)("structural"),
16101
+ type: import_types51.EdgeType.DEPENDS_ON,
16102
+ provenance: import_types51.Provenance.EXTRACTED,
16103
+ confidence: (0, import_types51.confidenceForExtracted)("structural"),
16012
16104
  evidence: { file: evidenceFile, line, snippet: key }
16013
16105
  };
16014
16106
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -16022,8 +16114,9 @@ async function addTerraformResources(graph, scanPath) {
16022
16114
  // src/extract/infra/k8s.ts
16023
16115
  init_cjs_shims();
16024
16116
  var import_node_fs29 = require("fs");
16025
- var import_node_path62 = __toESM(require("path"), 1);
16117
+ var import_node_path63 = __toESM(require("path"), 1);
16026
16118
  var import_yaml3 = require("yaml");
16119
+ var import_types52 = require("@neat.is/types");
16027
16120
  var K8S_KIND_TO_INFRA_KIND = {
16028
16121
  Service: "k8s-service",
16029
16122
  Deployment: "k8s-deployment",
@@ -16033,6 +16126,7 @@ var K8S_KIND_TO_INFRA_KIND = {
16033
16126
  Job: "k8s-job",
16034
16127
  Ingress: "k8s-ingress"
16035
16128
  };
16129
+ var WORKLOAD_KINDS = /* @__PURE__ */ new Set(["Deployment", "StatefulSet", "DaemonSet"]);
16036
16130
  async function walkYamlFiles2(start, depth = 0, max = 5) {
16037
16131
  if (depth > max) return [];
16038
16132
  const out = [];
@@ -16040,17 +16134,18 @@ async function walkYamlFiles2(start, depth = 0, max = 5) {
16040
16134
  for (const entry of entries) {
16041
16135
  if (entry.isDirectory()) {
16042
16136
  if (IGNORED_DIRS.has(entry.name)) continue;
16043
- const child = import_node_path62.default.join(start, entry.name);
16137
+ const child = import_node_path63.default.join(start, entry.name);
16044
16138
  if (await isPythonVenvDir(child)) continue;
16045
16139
  out.push(...await walkYamlFiles2(child, depth + 1, max));
16046
- } else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path62.default.extname(entry.name))) {
16047
- out.push(import_node_path62.default.join(start, entry.name));
16140
+ } else if (entry.isFile() && CONFIG_FILE_EXTENSIONS.has(import_node_path63.default.extname(entry.name))) {
16141
+ out.push(import_node_path63.default.join(start, entry.name));
16048
16142
  }
16049
16143
  }
16050
16144
  return out;
16051
16145
  }
16052
16146
  async function addK8sResources(graph, scanPath) {
16053
16147
  let nodesAdded = 0;
16148
+ let edgesAdded = 0;
16054
16149
  const files = await walkYamlFiles2(scanPath);
16055
16150
  for (const file of files) {
16056
16151
  const content = await import_node_fs29.promises.readFile(file, "utf8");
@@ -16060,31 +16155,63 @@ async function addK8sResources(graph, scanPath) {
16060
16155
  } catch {
16061
16156
  continue;
16062
16157
  }
16158
+ const relFile = toPosix(import_node_path63.default.relative(scanPath, file));
16063
16159
  for (const doc of docs) {
16064
16160
  if (!doc?.kind || !doc.metadata?.name) continue;
16065
16161
  const infraKind = K8S_KIND_TO_INFRA_KIND[doc.kind];
16066
16162
  if (!infraKind) continue;
16067
- const namespaced = doc.metadata.namespace ? `${doc.metadata.namespace}/${doc.metadata.name}` : doc.metadata.name;
16068
- const node = makeInfraNode(infraKind, namespaced, "kubernetes");
16163
+ const name = doc.metadata.name;
16164
+ const isWorkload = WORKLOAD_KINDS.has(doc.kind);
16165
+ const image = isWorkload ? doc.spec?.template?.spec?.containers?.[0]?.image : void 0;
16166
+ const replicas = isWorkload && typeof doc.spec?.replicas === "number" ? doc.spec.replicas : void 0;
16167
+ const base = makeInfraNode(infraKind, name, "kubernetes");
16168
+ const node = {
16169
+ ...base,
16170
+ ...doc.metadata.namespace ? { namespace: doc.metadata.namespace } : {},
16171
+ ...image ? { image } : {},
16172
+ ...replicas !== void 0 ? { replicas } : {}
16173
+ };
16069
16174
  if (!graph.hasNode(node.id)) {
16070
16175
  graph.addNode(node.id, node);
16071
16176
  nodesAdded++;
16072
16177
  }
16178
+ if (isWorkload) {
16179
+ const svcId = (0, import_types52.serviceId)(name);
16180
+ if (graph.hasNode(svcId)) {
16181
+ const svc = graph.getNodeAttributes(svcId);
16182
+ graph.replaceNodeAttributes(svcId, {
16183
+ ...svc,
16184
+ platform: svc.platform ?? "kubernetes",
16185
+ ...image ? { declaredImage: image } : {},
16186
+ ...replicas !== void 0 ? { declaredReplicas: replicas } : {}
16187
+ });
16188
+ edgesAdded += emitPlatformResourceEdge(
16189
+ graph,
16190
+ svcId,
16191
+ import_types52.EdgeType.RUNS_ON,
16192
+ infraKind,
16193
+ name,
16194
+ "kubernetes",
16195
+ relFile,
16196
+ lineContaining(content, image)
16197
+ ).edgesAdded;
16198
+ }
16199
+ }
16073
16200
  }
16074
16201
  }
16075
- return { nodesAdded, edgesAdded: 0 };
16202
+ return { nodesAdded, edgesAdded };
16076
16203
  }
16077
16204
 
16078
16205
  // src/extract/infra/cloudflare.ts
16079
16206
  init_cjs_shims();
16080
16207
  var import_node_fs30 = require("fs");
16081
- var import_node_path63 = __toESM(require("path"), 1);
16208
+ var import_node_path64 = __toESM(require("path"), 1);
16082
16209
  var import_smol_toml3 = require("smol-toml");
16083
- var import_types51 = require("@neat.is/types");
16210
+ var import_types53 = require("@neat.is/types");
16084
16211
  var WRANGLER_FILENAMES = ["wrangler.toml", "wrangler.jsonc", "wrangler.json"];
16085
16212
  async function readWranglerConfig(dir) {
16086
16213
  for (const filename of WRANGLER_FILENAMES) {
16087
- const abs = import_node_path63.default.join(dir, filename);
16214
+ const abs = import_node_path64.default.join(dir, filename);
16088
16215
  if (!await exists2(abs)) continue;
16089
16216
  const raw = await import_node_fs30.promises.readFile(abs, "utf8");
16090
16217
  const config = filename === "wrangler.toml" ? (0, import_smol_toml3.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
@@ -16128,8 +16255,8 @@ function addResourceEdge(graph, anchorId, edgeType, kind, name, evidenceFile, li
16128
16255
  source: anchorId,
16129
16256
  target: node.id,
16130
16257
  type: edgeType,
16131
- provenance: import_types51.Provenance.EXTRACTED,
16132
- confidence: (0, import_types51.confidenceForExtracted)("structural"),
16258
+ provenance: import_types53.Provenance.EXTRACTED,
16259
+ confidence: (0, import_types53.confidenceForExtracted)("structural"),
16133
16260
  evidence: { file: evidenceFile, ...line !== void 0 ? { line } : {} }
16134
16261
  };
16135
16262
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -16147,11 +16274,11 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16147
16274
  try {
16148
16275
  read = await readWranglerConfig(service.dir);
16149
16276
  } catch (err) {
16150
- recordExtractionError("infra cloudflare", import_node_path63.default.relative(scanPath, service.dir), err);
16277
+ recordExtractionError("infra cloudflare", import_node_path64.default.relative(scanPath, service.dir), err);
16151
16278
  continue;
16152
16279
  }
16153
16280
  if (!read || !read.config.name) continue;
16154
- const evidenceFile = toPosix(import_node_path63.default.relative(scanPath, import_node_path63.default.join(service.dir, read.relFile)));
16281
+ const evidenceFile = toPosix(import_node_path64.default.relative(scanPath, import_node_path64.default.join(service.dir, read.relFile)));
16155
16282
  discovered.push({ service, config: read.config, relFile: read.relFile, raw: read.raw, evidenceFile });
16156
16283
  }
16157
16284
  for (const worker of discovered) {
@@ -16163,7 +16290,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16163
16290
  }
16164
16291
  let anchorId = service.node.id;
16165
16292
  if (config.main) {
16166
- const entryRelPath = toPosix(import_node_path63.default.normalize(config.main));
16293
+ const entryRelPath = toPosix(import_node_path64.default.normalize(config.main));
16167
16294
  const { fileNodeId, nodesAdded: fn, edgesAdded: fe } = ensureFileNode(
16168
16295
  graph,
16169
16296
  service.pkg.name,
@@ -16190,15 +16317,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16190
16317
  nodesAdded++;
16191
16318
  }
16192
16319
  if (runtimeNode.id !== anchorId) {
16193
- const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id, import_types51.EdgeType.RUNS_ON);
16320
+ const runsOnId = (0, import_types3.extractedEdgeId)(anchorId, runtimeNode.id, import_types53.EdgeType.RUNS_ON);
16194
16321
  if (!graph.hasEdge(runsOnId)) {
16195
16322
  const edge = {
16196
16323
  id: runsOnId,
16197
16324
  source: anchorId,
16198
16325
  target: runtimeNode.id,
16199
- type: import_types51.EdgeType.RUNS_ON,
16200
- provenance: import_types51.Provenance.EXTRACTED,
16201
- confidence: (0, import_types51.confidenceForExtracted)("structural"),
16326
+ type: import_types53.EdgeType.RUNS_ON,
16327
+ provenance: import_types53.Provenance.EXTRACTED,
16328
+ confidence: (0, import_types53.confidenceForExtracted)("structural"),
16202
16329
  evidence: {
16203
16330
  file: evidenceFile,
16204
16331
  ...config.compatibility_date ? { snippet: `compatibility_date = ${config.compatibility_date}`.slice(0, 120) } : {}
@@ -16212,7 +16339,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16212
16339
  const result = addResourceEdge(
16213
16340
  graph,
16214
16341
  anchorId,
16215
- import_types51.EdgeType.CONNECTS_TO,
16342
+ import_types53.EdgeType.CONNECTS_TO,
16216
16343
  "cloudflare-route",
16217
16344
  route,
16218
16345
  evidenceFile,
@@ -16236,7 +16363,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16236
16363
  const result = addResourceEdge(
16237
16364
  graph,
16238
16365
  anchorId,
16239
- import_types51.EdgeType.DEPENDS_ON,
16366
+ import_types53.EdgeType.DEPENDS_ON,
16240
16367
  group.kind,
16241
16368
  name,
16242
16369
  evidenceFile,
@@ -16250,7 +16377,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16250
16377
  const result = addResourceEdge(
16251
16378
  graph,
16252
16379
  anchorId,
16253
- import_types51.EdgeType.DEPENDS_ON,
16380
+ import_types53.EdgeType.DEPENDS_ON,
16254
16381
  "cloudflare-cron",
16255
16382
  cron,
16256
16383
  evidenceFile,
@@ -16263,7 +16390,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16263
16390
  const result = addResourceEdge(
16264
16391
  graph,
16265
16392
  anchorId,
16266
- import_types51.EdgeType.DEPENDS_ON,
16393
+ import_types53.EdgeType.DEPENDS_ON,
16267
16394
  "cloudflare-env-var",
16268
16395
  varName,
16269
16396
  evidenceFile,
@@ -16276,15 +16403,15 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16276
16403
  if (!svc.service) continue;
16277
16404
  const target = workerIndex.get(svc.service);
16278
16405
  if (target && target.anchorId !== anchorId) {
16279
- const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId, import_types51.EdgeType.CALLS);
16406
+ const edgeId = (0, import_types3.extractedEdgeId)(anchorId, target.anchorId, import_types53.EdgeType.CALLS);
16280
16407
  if (!graph.hasEdge(edgeId)) {
16281
16408
  const edge = {
16282
16409
  id: edgeId,
16283
16410
  source: anchorId,
16284
16411
  target: target.anchorId,
16285
- type: import_types51.EdgeType.CALLS,
16286
- provenance: import_types51.Provenance.EXTRACTED,
16287
- confidence: (0, import_types51.confidenceForExtracted)("structural"),
16412
+ type: import_types53.EdgeType.CALLS,
16413
+ provenance: import_types53.Provenance.EXTRACTED,
16414
+ confidence: (0, import_types53.confidenceForExtracted)("structural"),
16288
16415
  evidence: { file: evidenceFile, line: lineContaining2(raw, svc.service) }
16289
16416
  };
16290
16417
  graph.addEdgeWithKey(edgeId, edge.source, edge.target, edge);
@@ -16295,7 +16422,7 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16295
16422
  const result = addResourceEdge(
16296
16423
  graph,
16297
16424
  anchorId,
16298
- import_types51.EdgeType.DEPENDS_ON,
16425
+ import_types53.EdgeType.DEPENDS_ON,
16299
16426
  "cloudflare-service-binding",
16300
16427
  svc.service,
16301
16428
  evidenceFile,
@@ -16311,12 +16438,12 @@ async function addCloudflareWorkers(graph, services, scanPath) {
16311
16438
  // src/extract/infra/vercel.ts
16312
16439
  init_cjs_shims();
16313
16440
  var import_node_fs31 = require("fs");
16314
- var import_node_path64 = __toESM(require("path"), 1);
16315
- var import_types52 = require("@neat.is/types");
16441
+ var import_node_path65 = __toESM(require("path"), 1);
16442
+ var import_types54 = require("@neat.is/types");
16316
16443
  var VERCEL_CONFIG_FILENAMES = ["vercel.json", "vercel.jsonc"];
16317
16444
  async function readVercelConfig(dir) {
16318
16445
  for (const filename of VERCEL_CONFIG_FILENAMES) {
16319
- const abs = import_node_path64.default.join(dir, filename);
16446
+ const abs = import_node_path65.default.join(dir, filename);
16320
16447
  if (!await exists2(abs)) continue;
16321
16448
  const raw = await import_node_fs31.promises.readFile(abs, "utf8");
16322
16449
  const config = JSON.parse(maskCommentsInSource(raw));
@@ -16325,7 +16452,7 @@ async function readVercelConfig(dir) {
16325
16452
  return null;
16326
16453
  }
16327
16454
  async function readLinkedProjectName(dir) {
16328
- const abs = import_node_path64.default.join(dir, ".vercel", "project.json");
16455
+ const abs = import_node_path65.default.join(dir, ".vercel", "project.json");
16329
16456
  if (!await exists2(abs)) return void 0;
16330
16457
  const parsed = JSON.parse(await import_node_fs31.promises.readFile(abs, "utf8"));
16331
16458
  return typeof parsed.projectName === "string" ? parsed.projectName : void 0;
@@ -16343,7 +16470,7 @@ async function addVercelServices(graph, services, scanPath) {
16343
16470
  read = await readVercelConfig(service.dir);
16344
16471
  projectName = await readLinkedProjectName(service.dir);
16345
16472
  } catch (err) {
16346
- recordExtractionError("infra vercel", import_node_path64.default.relative(scanPath, service.dir), err);
16473
+ recordExtractionError("infra vercel", import_node_path65.default.relative(scanPath, service.dir), err);
16347
16474
  continue;
16348
16475
  }
16349
16476
  if (!read && !projectName) continue;
@@ -16359,7 +16486,7 @@ async function addVercelServices(graph, services, scanPath) {
16359
16486
  const anchorId = service.node.id;
16360
16487
  if (!read) continue;
16361
16488
  const { config, relFile, raw } = read;
16362
- const evidenceFile = toPosix(import_node_path64.default.relative(scanPath, import_node_path64.default.join(service.dir, relFile)));
16489
+ const evidenceFile = toPosix(import_node_path65.default.relative(scanPath, import_node_path65.default.join(service.dir, relFile)));
16363
16490
  const add = (edgeType, kind, name) => {
16364
16491
  if (!name) return;
16365
16492
  const result = emitPlatformResourceEdge(
@@ -16375,12 +16502,12 @@ async function addVercelServices(graph, services, scanPath) {
16375
16502
  nodesAdded += result.nodesAdded;
16376
16503
  edgesAdded += result.edgesAdded;
16377
16504
  };
16378
- add(import_types52.EdgeType.RUNS_ON, "vercel", "vercel");
16379
- for (const cron of config.crons ?? []) add(import_types52.EdgeType.DEPENDS_ON, "vercel-cron", cron.path ?? cron.schedule);
16380
- for (const varName of Object.keys(config.env ?? {})) add(import_types52.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16381
- for (const varName of Object.keys(config.build?.env ?? {})) add(import_types52.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16505
+ add(import_types54.EdgeType.RUNS_ON, "vercel", "vercel");
16506
+ for (const cron of config.crons ?? []) add(import_types54.EdgeType.DEPENDS_ON, "vercel-cron", cron.path ?? cron.schedule);
16507
+ for (const varName of Object.keys(config.env ?? {})) add(import_types54.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16508
+ for (const varName of Object.keys(config.build?.env ?? {})) add(import_types54.EdgeType.DEPENDS_ON, "vercel-env-var", varName);
16382
16509
  for (const route of [...config.rewrites ?? [], ...config.redirects ?? [], ...config.routes ?? []]) {
16383
- add(import_types52.EdgeType.CONNECTS_TO, "vercel-route", routeSource(route));
16510
+ add(import_types54.EdgeType.CONNECTS_TO, "vercel-route", routeSource(route));
16384
16511
  }
16385
16512
  }
16386
16513
  return { nodesAdded, edgesAdded };
@@ -16389,13 +16516,13 @@ async function addVercelServices(graph, services, scanPath) {
16389
16516
  // src/extract/infra/railway.ts
16390
16517
  init_cjs_shims();
16391
16518
  var import_node_fs32 = require("fs");
16392
- var import_node_path65 = __toESM(require("path"), 1);
16519
+ var import_node_path66 = __toESM(require("path"), 1);
16393
16520
  var import_smol_toml4 = require("smol-toml");
16394
- var import_types53 = require("@neat.is/types");
16521
+ var import_types55 = require("@neat.is/types");
16395
16522
  var RAILWAY_FILENAMES = ["railway.toml", "railway.json", "railway.jsonc"];
16396
16523
  async function readRailwayConfig(dir) {
16397
16524
  for (const filename of RAILWAY_FILENAMES) {
16398
- const abs = import_node_path65.default.join(dir, filename);
16525
+ const abs = import_node_path66.default.join(dir, filename);
16399
16526
  if (!await exists2(abs)) continue;
16400
16527
  const raw = await import_node_fs32.promises.readFile(abs, "utf8");
16401
16528
  const config = filename === "railway.toml" ? (0, import_smol_toml4.parse)(raw) : JSON.parse(maskCommentsInSource(raw));
@@ -16411,7 +16538,7 @@ async function addRailwayServices(graph, services, scanPath) {
16411
16538
  try {
16412
16539
  read = await readRailwayConfig(service.dir);
16413
16540
  } catch (err) {
16414
- recordExtractionError("infra railway", import_node_path65.default.relative(scanPath, service.dir), err);
16541
+ recordExtractionError("infra railway", import_node_path66.default.relative(scanPath, service.dir), err);
16415
16542
  continue;
16416
16543
  }
16417
16544
  if (!read) continue;
@@ -16421,7 +16548,7 @@ async function addRailwayServices(graph, services, scanPath) {
16421
16548
  }
16422
16549
  const anchorId = service.node.id;
16423
16550
  const { config, relFile, raw } = read;
16424
- const evidenceFile = toPosix(import_node_path65.default.relative(scanPath, import_node_path65.default.join(service.dir, relFile)));
16551
+ const evidenceFile = toPosix(import_node_path66.default.relative(scanPath, import_node_path66.default.join(service.dir, relFile)));
16425
16552
  const add = (edgeType, kind, name) => {
16426
16553
  if (!name) return;
16427
16554
  const result = emitPlatformResourceEdge(
@@ -16437,9 +16564,9 @@ async function addRailwayServices(graph, services, scanPath) {
16437
16564
  nodesAdded += result.nodesAdded;
16438
16565
  edgesAdded += result.edgesAdded;
16439
16566
  };
16440
- add(import_types53.EdgeType.RUNS_ON, "railway", "railway");
16441
- add(import_types53.EdgeType.CONNECTS_TO, "railway-route", config.deploy?.healthcheckPath);
16442
- add(import_types53.EdgeType.DEPENDS_ON, "railway-cron", config.deploy?.cronSchedule);
16567
+ add(import_types55.EdgeType.RUNS_ON, "railway", "railway");
16568
+ add(import_types55.EdgeType.CONNECTS_TO, "railway-route", config.deploy?.healthcheckPath);
16569
+ add(import_types55.EdgeType.DEPENDS_ON, "railway-cron", config.deploy?.cronSchedule);
16443
16570
  }
16444
16571
  return { nodesAdded, edgesAdded };
16445
16572
  }
@@ -16447,12 +16574,12 @@ async function addRailwayServices(graph, services, scanPath) {
16447
16574
  // src/extract/infra/supabase.ts
16448
16575
  init_cjs_shims();
16449
16576
  var import_node_fs33 = require("fs");
16450
- var import_node_path66 = __toESM(require("path"), 1);
16577
+ var import_node_path67 = __toESM(require("path"), 1);
16451
16578
  var import_smol_toml5 = require("smol-toml");
16452
- var import_types54 = require("@neat.is/types");
16579
+ var import_types56 = require("@neat.is/types");
16453
16580
  async function readSupabaseConfig(dir) {
16454
- const relFile = import_node_path66.default.join("supabase", "config.toml");
16455
- const abs = import_node_path66.default.join(dir, relFile);
16581
+ const relFile = import_node_path67.default.join("supabase", "config.toml");
16582
+ const abs = import_node_path67.default.join(dir, relFile);
16456
16583
  if (!await exists2(abs)) return null;
16457
16584
  const raw = await import_node_fs33.promises.readFile(abs, "utf8");
16458
16585
  const config = (0, import_smol_toml5.parse)(raw);
@@ -16466,7 +16593,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
16466
16593
  try {
16467
16594
  read = await readSupabaseConfig(service.dir);
16468
16595
  } catch (err) {
16469
- recordExtractionError("infra supabase", import_node_path66.default.relative(scanPath, service.dir), err);
16596
+ recordExtractionError("infra supabase", import_node_path67.default.relative(scanPath, service.dir), err);
16470
16597
  continue;
16471
16598
  }
16472
16599
  if (!read) continue;
@@ -16481,7 +16608,7 @@ async function addSupabaseProjects(graph, services, scanPath) {
16481
16608
  });
16482
16609
  }
16483
16610
  const anchorId = service.node.id;
16484
- const evidenceFile = toPosix(import_node_path66.default.relative(scanPath, import_node_path66.default.join(service.dir, relFile)));
16611
+ const evidenceFile = toPosix(import_node_path67.default.relative(scanPath, import_node_path67.default.join(service.dir, relFile)));
16485
16612
  const add = (edgeType, kind, name) => {
16486
16613
  if (!name) return;
16487
16614
  const result = emitPlatformResourceEdge(
@@ -16497,10 +16624,10 @@ async function addSupabaseProjects(graph, services, scanPath) {
16497
16624
  nodesAdded += result.nodesAdded;
16498
16625
  edgesAdded += result.edgesAdded;
16499
16626
  };
16500
- add(import_types54.EdgeType.RUNS_ON, "supabase", "supabase");
16501
- for (const fn of Object.keys(config.functions ?? {})) add(import_types54.EdgeType.DEPENDS_ON, "supabase-function", fn);
16502
- if (config.storage) add(import_types54.EdgeType.DEPENDS_ON, "supabase-storage", "storage");
16503
- if (config.auth) add(import_types54.EdgeType.DEPENDS_ON, "supabase-auth", "auth");
16627
+ add(import_types56.EdgeType.RUNS_ON, "supabase", "supabase");
16628
+ for (const fn of Object.keys(config.functions ?? {})) add(import_types56.EdgeType.DEPENDS_ON, "supabase-function", fn);
16629
+ if (config.storage) add(import_types56.EdgeType.DEPENDS_ON, "supabase-storage", "storage");
16630
+ if (config.auth) add(import_types56.EdgeType.DEPENDS_ON, "supabase-auth", "auth");
16504
16631
  }
16505
16632
  return { nodesAdded, edgesAdded };
16506
16633
  }
@@ -16523,18 +16650,18 @@ async function addInfra(graph, scanPath, services) {
16523
16650
 
16524
16651
  // src/extract/zod-shapes.ts
16525
16652
  init_cjs_shims();
16526
- var import_node_path67 = __toESM(require("path"), 1);
16527
- var import_tree_sitter17 = __toESM(require("tree-sitter"), 1);
16653
+ var import_node_path68 = __toESM(require("path"), 1);
16654
+ var import_tree_sitter18 = __toESM(require("tree-sitter"), 1);
16528
16655
  var import_tree_sitter_javascript8 = __toESM(require("tree-sitter-javascript"), 1);
16529
- var import_types55 = require("@neat.is/types");
16656
+ var import_types57 = require("@neat.is/types");
16530
16657
  var ZOD_IMPORT_RE = /\bzod\b/;
16531
16658
  var ZOD_OBJECTS = /* @__PURE__ */ new Set(["z", "zod"]);
16532
16659
  function parserForExt4(ext) {
16533
- const p = new import_tree_sitter17.default();
16660
+ const p = new import_tree_sitter18.default();
16534
16661
  p.setLanguage(GRAMMAR_BY_EXT[ext] ?? import_tree_sitter_javascript8.default);
16535
16662
  return p;
16536
16663
  }
16537
- function namedChildren5(node) {
16664
+ function namedChildren6(node) {
16538
16665
  const out = [];
16539
16666
  for (let i = 0; i < node.namedChildCount; i++) {
16540
16667
  const c = node.namedChild(i);
@@ -16544,7 +16671,7 @@ function namedChildren5(node) {
16544
16671
  }
16545
16672
  function stringLiteralText5(node) {
16546
16673
  if (!node || node.type !== "string") return null;
16547
- for (const child of namedChildren5(node)) {
16674
+ for (const child of namedChildren6(node)) {
16548
16675
  if (child.type === "string_fragment") return child.text;
16549
16676
  }
16550
16677
  return "";
@@ -16569,12 +16696,12 @@ function zodCallKind(call) {
16569
16696
  function firstArg(call) {
16570
16697
  const args = call.childForFieldName("arguments");
16571
16698
  if (!args) return null;
16572
- return namedChildren5(args)[0] ?? null;
16699
+ return namedChildren6(args)[0] ?? null;
16573
16700
  }
16574
16701
  function fieldsFromObject(obj) {
16575
16702
  const out = [];
16576
16703
  const seen = /* @__PURE__ */ new Set();
16577
- for (const child of namedChildren5(obj)) {
16704
+ for (const child of namedChildren6(obj)) {
16578
16705
  if (child.type === "spread_element") return null;
16579
16706
  if (child.type !== "pair") continue;
16580
16707
  const key = child.childForFieldName("key");
@@ -16590,7 +16717,7 @@ function fieldsFromObject(obj) {
16590
16717
  function membersFromEnum(arr) {
16591
16718
  const out = [];
16592
16719
  const seen = /* @__PURE__ */ new Set();
16593
- for (const child of namedChildren5(arr)) {
16720
+ for (const child of namedChildren6(arr)) {
16594
16721
  if (child.type !== "string") return null;
16595
16722
  const value = stringLiteralText5(child);
16596
16723
  if (value !== null && value !== "" && !seen.has(value)) {
@@ -16602,10 +16729,10 @@ function membersFromEnum(arr) {
16602
16729
  }
16603
16730
  function topLevelSchemas(root) {
16604
16731
  const out = [];
16605
- for (const stmt of namedChildren5(root)) {
16732
+ for (const stmt of namedChildren6(root)) {
16606
16733
  const decl = stmt.type === "export_statement" ? stmt.childForFieldName("declaration") : stmt;
16607
16734
  if (decl?.type !== "lexical_declaration" && decl?.type !== "variable_declaration") continue;
16608
- for (const declarator of namedChildren5(decl)) {
16735
+ for (const declarator of namedChildren6(decl)) {
16609
16736
  if (declarator.type !== "variable_declarator") continue;
16610
16737
  const name = declarator.childForFieldName("name");
16611
16738
  const value = declarator.childForFieldName("value");
@@ -16618,7 +16745,7 @@ function topLevelSchemas(root) {
16618
16745
  }
16619
16746
  function zodShapesFromFile(file, serviceDir) {
16620
16747
  if (!ZOD_IMPORT_RE.test(file.content)) return [];
16621
- const tree = parseSource3(parserForExt4(import_node_path67.default.extname(file.path)), file.content);
16748
+ const tree = parseSource3(parserForExt4(import_node_path68.default.extname(file.path)), file.content);
16622
16749
  const out = [];
16623
16750
  const seen = /* @__PURE__ */ new Set();
16624
16751
  for (const { name, call } of topLevelSchemas(tree.rootNode)) {
@@ -16632,11 +16759,11 @@ function zodShapesFromFile(file, serviceDir) {
16632
16759
  seen.add(name);
16633
16760
  const line = call.startPosition.row + 1;
16634
16761
  out.push({
16635
- infraId: (0, import_types55.infraId)("zod-schema", name),
16762
+ infraId: (0, import_types57.infraId)("zod-schema", name),
16636
16763
  name,
16637
16764
  fields,
16638
16765
  evidence: {
16639
- file: import_node_path67.default.relative(serviceDir, file.path),
16766
+ file: import_node_path68.default.relative(serviceDir, file.path),
16640
16767
  line,
16641
16768
  snippet: snippet(file.content, line)
16642
16769
  }
@@ -16667,7 +16794,7 @@ async function addZodShapes(graph, services) {
16667
16794
  if (!graph.hasNode(shape.infraId)) {
16668
16795
  const node = {
16669
16796
  id: shape.infraId,
16670
- type: import_types55.NodeType.InfraNode,
16797
+ type: import_types57.NodeType.InfraNode,
16671
16798
  name: shape.name,
16672
16799
  provider: "self",
16673
16800
  kind: "zod-schema"
@@ -16677,14 +16804,14 @@ async function addZodShapes(graph, services) {
16677
16804
  }
16678
16805
  if (shape.fields.length > 0) {
16679
16806
  const node = graph.getNodeAttributes(shape.infraId);
16680
- if (node.type === import_types55.NodeType.InfraNode) {
16807
+ if (node.type === import_types57.NodeType.InfraNode) {
16681
16808
  graph.replaceNodeAttributes(shape.infraId, {
16682
16809
  ...node,
16683
16810
  columns: foldColumns(
16684
16811
  node.columns,
16685
16812
  shape.fields,
16686
- import_types55.Provenance.EXTRACTED,
16687
- (0, import_types55.confidenceForExtracted)("structural")
16813
+ import_types57.Provenance.EXTRACTED,
16814
+ (0, import_types57.confidenceForExtracted)("structural")
16688
16815
  )
16689
16816
  });
16690
16817
  }
@@ -16698,15 +16825,15 @@ async function addZodShapes(graph, services) {
16698
16825
  );
16699
16826
  nodesAdded += n;
16700
16827
  edgesAdded += e;
16701
- const edgeId = (0, import_types55.extractedEdgeId)(fileNodeId, shape.infraId, import_types55.EdgeType.CONTAINS);
16828
+ const edgeId = (0, import_types57.extractedEdgeId)(fileNodeId, shape.infraId, import_types57.EdgeType.CONTAINS);
16702
16829
  if (!graph.hasEdge(edgeId)) {
16703
16830
  const edge = {
16704
16831
  id: edgeId,
16705
16832
  source: fileNodeId,
16706
16833
  target: shape.infraId,
16707
- type: import_types55.EdgeType.CONTAINS,
16708
- provenance: import_types55.Provenance.EXTRACTED,
16709
- confidence: (0, import_types55.confidenceForExtracted)("structural"),
16834
+ type: import_types57.EdgeType.CONTAINS,
16835
+ provenance: import_types57.Provenance.EXTRACTED,
16836
+ confidence: (0, import_types57.confidenceForExtracted)("structural"),
16710
16837
  evidence: shape.evidence
16711
16838
  };
16712
16839
  graph.addEdgeWithKey(edgeId, fileNodeId, shape.infraId, edge);
@@ -16720,7 +16847,7 @@ async function addZodShapes(graph, services) {
16720
16847
 
16721
16848
  // src/extract/firestore-rules.ts
16722
16849
  init_cjs_shims();
16723
- var import_types56 = require("@neat.is/types");
16850
+ var import_types58 = require("@neat.is/types");
16724
16851
  var FIRESTORE_COLLECTION_KIND = "firestore-collection";
16725
16852
  var WRITE_METHODS = /* @__PURE__ */ new Set(["write", "create", "update"]);
16726
16853
  function stripComments(src) {
@@ -16860,7 +16987,7 @@ async function addFirestoreRules(graph, services) {
16860
16987
  if (guards.size === 0) return { nodesAdded: 0, edgesAdded: 0 };
16861
16988
  graph.forEachNode((id, attrs) => {
16862
16989
  const node = attrs;
16863
- if (node.type !== import_types56.NodeType.InfraNode) return;
16990
+ if (node.type !== import_types58.NodeType.InfraNode) return;
16864
16991
  if (node.kind !== FIRESTORE_COLLECTION_KIND) return;
16865
16992
  const fields = guards.get(collectionKeyFromName(node.name));
16866
16993
  if (!fields || fields.size === 0) return;
@@ -16873,17 +17000,17 @@ async function addFirestoreRules(graph, services) {
16873
17000
  }
16874
17001
 
16875
17002
  // src/extract/index.ts
16876
- var import_node_path69 = __toESM(require("path"), 1);
17003
+ var import_node_path70 = __toESM(require("path"), 1);
16877
17004
 
16878
17005
  // src/extract/retire.ts
16879
17006
  init_cjs_shims();
16880
17007
  var import_node_fs34 = require("fs");
16881
- var import_node_path68 = __toESM(require("path"), 1);
16882
- var import_types57 = require("@neat.is/types");
17008
+ var import_node_path69 = __toESM(require("path"), 1);
17009
+ var import_types59 = require("@neat.is/types");
16883
17010
  function dropOrphanedFileNodes(graph) {
16884
17011
  const orphans = [];
16885
17012
  graph.forEachNode((id, attrs) => {
16886
- if (attrs.type !== import_types57.NodeType.FileNode) return;
17013
+ if (attrs.type !== import_types59.NodeType.FileNode) return;
16887
17014
  if (graph.inboundEdges(id).length === 0 && graph.outboundEdges(id).length === 0) {
16888
17015
  orphans.push(id);
16889
17016
  }
@@ -16896,14 +17023,14 @@ function retireExtractedEdgesByMissingFile(graph, scanPath, serviceDirs = []) {
16896
17023
  const bases = [scanPath, ...serviceDirs];
16897
17024
  graph.forEachEdge((id, attrs) => {
16898
17025
  const edge = attrs;
16899
- if (edge.provenance !== import_types57.Provenance.EXTRACTED) return;
17026
+ if (edge.provenance !== import_types59.Provenance.EXTRACTED) return;
16900
17027
  const evidenceFile = edge.evidence?.file;
16901
17028
  if (!evidenceFile) return;
16902
- if (import_node_path68.default.isAbsolute(evidenceFile)) {
17029
+ if (import_node_path69.default.isAbsolute(evidenceFile)) {
16903
17030
  if (!(0, import_node_fs34.existsSync)(evidenceFile)) toDrop.push(id);
16904
17031
  return;
16905
17032
  }
16906
- const found = bases.some((base) => (0, import_node_fs34.existsSync)(import_node_path68.default.join(base, evidenceFile)));
17033
+ const found = bases.some((base) => (0, import_node_fs34.existsSync)(import_node_path69.default.join(base, evidenceFile)));
16907
17034
  if (!found) toDrop.push(id);
16908
17035
  });
16909
17036
  for (const id of toDrop) graph.dropEdge(id);
@@ -16960,7 +17087,7 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
16960
17087
  }
16961
17088
  const droppedEntries = drainDroppedExtracted();
16962
17089
  if (isRejectedLogEnabled() && opts.errorsPath && droppedEntries.length > 0) {
16963
- const rejectedPath = import_node_path69.default.join(import_node_path69.default.dirname(opts.errorsPath), "rejected.ndjson");
17090
+ const rejectedPath = import_node_path70.default.join(import_node_path70.default.dirname(opts.errorsPath), "rejected.ndjson");
16964
17091
  try {
16965
17092
  await writeRejectedExtracted(droppedEntries, rejectedPath);
16966
17093
  } catch (err) {
@@ -16994,7 +17121,7 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
16994
17121
 
16995
17122
  // src/goodybag.ts
16996
17123
  init_cjs_shims();
16997
- var import_types58 = require("@neat.is/types");
17124
+ var import_types60 = require("@neat.is/types");
16998
17125
  var CODE_FILEPATH_ATTR2 = "code.filepath";
16999
17126
  var CODE_LINENO_ATTR2 = "code.lineno";
17000
17127
  var BLAST_NEAREST_LIMIT = 5;
@@ -17019,7 +17146,7 @@ function locusOf(graph, ev) {
17019
17146
  ...Number.isFinite(line) ? { lineStart: line, lineEnd: line } : {},
17020
17147
  ...node?.name ? { symbol: node.name } : {},
17021
17148
  service: node?.service ?? ev.service,
17022
- provenance: import_types58.Provenance.OBSERVED
17149
+ provenance: import_types60.Provenance.OBSERVED
17023
17150
  };
17024
17151
  }
17025
17152
  function locusFromNode(graph, nodeId) {
@@ -17035,7 +17162,7 @@ function locusFromNode(graph, nodeId) {
17035
17162
  ...typeof end === "number" ? { lineEnd: end } : {},
17036
17163
  ...n.qualname ? { symbol: shortLabel(graph, nodeId) } : {},
17037
17164
  ...n.service ? { service: n.service } : {},
17038
- provenance: import_types58.Provenance.INFERRED
17165
+ provenance: import_types60.Provenance.INFERRED
17039
17166
  };
17040
17167
  }
17041
17168
  function promoteCauseLocus(graph, causeNode, incidents) {
@@ -17044,7 +17171,7 @@ function promoteCauseLocus(graph, causeNode, incidents) {
17044
17171
  );
17045
17172
  if (native) {
17046
17173
  const l = locusOf(graph, native);
17047
- if (l) return { ...l, symbol: shortLabel(graph, causeNode), provenance: import_types58.Provenance.INFERRED };
17174
+ if (l) return { ...l, symbol: shortLabel(graph, causeNode), provenance: import_types60.Provenance.INFERRED };
17048
17175
  }
17049
17176
  return locusFromNode(graph, causeNode);
17050
17177
  }
@@ -17093,7 +17220,7 @@ function buildIncidentCard(graph, errorEvent, incidents, policies) {
17093
17220
  const chain = (rc.traversalPath ?? []).map((node, i) => ({
17094
17221
  node,
17095
17222
  grain: grainOf2(graph, node),
17096
- provenance: provs[i] ?? provs[provs.length - 1] ?? import_types58.Provenance.INFERRED
17223
+ provenance: provs[i] ?? provs[provs.length - 1] ?? import_types60.Provenance.INFERRED
17097
17224
  }));
17098
17225
  rootCause = {
17099
17226
  node: rc.rootCauseNode,
@@ -17123,7 +17250,7 @@ function buildIncidentCard(graph, errorEvent, incidents, policies) {
17123
17250
  kind: "incident",
17124
17251
  id: errorEvent.id,
17125
17252
  at: errorEvent.timestamp,
17126
- incidentKind: (0, import_types58.incidentKindOf)(errorEvent),
17253
+ incidentKind: (0, import_types60.incidentKindOf)(errorEvent),
17127
17254
  service: errorEvent.service,
17128
17255
  affectedNode: affected,
17129
17256
  message: errorEvent.errorMessage,
@@ -17140,12 +17267,12 @@ function buildIncidentCard(graph, errorEvent, incidents, policies) {
17140
17267
  ...divergences.length > 0 ? { divergence: divergences } : {},
17141
17268
  headline: renderHeadline(graph, errorEvent, locus, rootCause?.node ?? null)
17142
17269
  };
17143
- return import_types58.IncidentCardSchema.parse(card);
17270
+ return import_types60.IncidentCardSchema.parse(card);
17144
17271
  }
17145
17272
 
17146
17273
  // src/ask.ts
17147
17274
  init_cjs_shims();
17148
- var import_types59 = require("@neat.is/types");
17275
+ var import_types61 = require("@neat.is/types");
17149
17276
  var DEFAULT_MAX_NODES = 3;
17150
17277
  var MAX_FACTS_PER_SECTION = 6;
17151
17278
  var INTENT_RULES = [
@@ -17373,7 +17500,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
17373
17500
  };
17374
17501
  graph.forEachNode((id, attrs) => {
17375
17502
  const node = attrs;
17376
- if (node.type === import_types59.NodeType.FrontierNode) return;
17503
+ if (node.type === import_types61.NodeType.FrontierNode) return;
17377
17504
  const name = nodeName(node);
17378
17505
  const body = idBody(id);
17379
17506
  const labelTokens = /* @__PURE__ */ new Set([...tokens(body), ...tokens(name)]);
@@ -17392,7 +17519,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
17392
17519
  const res = await searchIndex.search(question, 10);
17393
17520
  if (res.provider !== "substring") {
17394
17521
  for (const m of res.matches) {
17395
- if (m.node.type === import_types59.NodeType.FrontierNode) continue;
17522
+ if (m.node.type === import_types61.NodeType.FrontierNode) continue;
17396
17523
  const already = best.get(m.node.id);
17397
17524
  if (!already && m.score < EMBED_MIN_SCORE) continue;
17398
17525
  consider({
@@ -17430,7 +17557,7 @@ function edgeSignalNote(e) {
17430
17557
  function buildRootCauseSection(graph, node, incidents, now) {
17431
17558
  const result = getRootCause(graph, node, void 0, incidents, { now });
17432
17559
  if (!result) return null;
17433
- const lastProv = result.edgeProvenances[result.edgeProvenances.length - 1] ?? import_types59.Provenance.OBSERVED;
17560
+ const lastProv = result.edgeProvenances[result.edgeProvenances.length - 1] ?? import_types61.Provenance.OBSERVED;
17434
17561
  const facts = [
17435
17562
  {
17436
17563
  text: `Root cause: ${result.rootCauseNode} \u2014 ${result.rootCauseReason}`,
@@ -17480,7 +17607,7 @@ function buildObservedSection(graph, node) {
17480
17607
  if (result.observed && result.inboundObservedCount > 0) {
17481
17608
  facts.push({
17482
17609
  text: `no outbound runtime calls, but OTel observed ${result.inboundObservedCount} inbound call path${result.inboundObservedCount === 1 ? "" : "s"} \u2014 a pure receiver`,
17483
- provenance: import_types59.Provenance.OBSERVED
17610
+ provenance: import_types61.Provenance.OBSERVED
17484
17611
  });
17485
17612
  } else {
17486
17613
  return null;
@@ -17508,7 +17635,7 @@ function buildIncidentsSection(node, incidents) {
17508
17635
  const facts = ordered.map((ev) => ({
17509
17636
  text: `${ev.timestamp} \u2014 ${ev.service}: ${ev.errorMessage}`,
17510
17637
  // ErrorEvents are observation records — OBSERVED by definition.
17511
- provenance: import_types59.Provenance.OBSERVED
17638
+ provenance: import_types61.Provenance.OBSERVED
17512
17639
  }));
17513
17640
  return { heading: `Recent incidents (OBSERVED) \u2014 ${relevant.length} recorded`, facts };
17514
17641
  }
@@ -17568,7 +17695,7 @@ function buildGlobalIncidentsSection(incidents) {
17568
17695
  }
17569
17696
  const byKey = /* @__PURE__ */ new Map();
17570
17697
  for (const ev of incidents) {
17571
- const key = ev.affectedNode || (0, import_types59.serviceId)(ev.service);
17698
+ const key = ev.affectedNode || (0, import_types61.serviceId)(ev.service);
17572
17699
  const cur = byKey.get(key);
17573
17700
  if (!cur) {
17574
17701
  byKey.set(key, { key, count: 1, latest: ev.timestamp, sampleMsg: ev.errorMessage });
@@ -17583,7 +17710,7 @@ function buildGlobalIncidentsSection(incidents) {
17583
17710
  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);
17584
17711
  const facts = rows.map((r) => ({
17585
17712
  text: `${r.key} \u2014 ${r.count} incident${r.count === 1 ? "" : "s"}, latest ${r.latest}: ${r.sampleMsg}`,
17586
- provenance: import_types59.Provenance.OBSERVED
17713
+ provenance: import_types61.Provenance.OBSERVED
17587
17714
  }));
17588
17715
  return {
17589
17716
  heading: `Incidents across the system \u2014 ${incidents.length} recorded`,
@@ -17596,7 +17723,7 @@ function buildOverviewSections(graph, incidents) {
17596
17723
  graph.forEachNode((_id, attrs) => {
17597
17724
  const node = attrs;
17598
17725
  nodeByType.set(node.type, (nodeByType.get(node.type) ?? 0) + 1);
17599
- if (node.type === import_types59.NodeType.ServiceNode) services.push(node.id);
17726
+ if (node.type === import_types61.NodeType.ServiceNode) services.push(node.id);
17600
17727
  });
17601
17728
  const edgeByProv = /* @__PURE__ */ new Map();
17602
17729
  graph.forEachEdge((_id, attrs) => {
@@ -17608,10 +17735,10 @@ function buildOverviewSections(graph, incidents) {
17608
17735
  const shapeFacts = [
17609
17736
  { text: `${graph.order} nodes, ${graph.size} edges` },
17610
17737
  {
17611
- 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`
17738
+ text: `${count(import_types61.NodeType.ServiceNode)} services, ${count(import_types61.NodeType.FileNode)} files, ${count(import_types61.NodeType.SymbolNode)} symbols, ${count(import_types61.NodeType.DatabaseNode)} databases`
17612
17739
  }
17613
17740
  ];
17614
- for (const p of [import_types59.Provenance.EXTRACTED, import_types59.Provenance.OBSERVED, import_types59.Provenance.INFERRED, import_types59.Provenance.STALE]) {
17741
+ for (const p of [import_types61.Provenance.EXTRACTED, import_types61.Provenance.OBSERVED, import_types61.Provenance.INFERRED, import_types61.Provenance.STALE]) {
17615
17742
  const n = edgeByProv.get(p) ?? 0;
17616
17743
  if (n > 0) shapeFacts.push({ text: `${n} ${p} edge${n === 1 ? "" : "s"}`, provenance: p });
17617
17744
  }
@@ -17628,7 +17755,7 @@ function buildOverviewSections(graph, incidents) {
17628
17755
  if (incidents && incidents.length > 0) {
17629
17756
  const incCount = /* @__PURE__ */ new Map();
17630
17757
  for (const ev of incidents) {
17631
- const key = ev.affectedNode || (0, import_types59.serviceId)(ev.service);
17758
+ const key = ev.affectedNode || (0, import_types61.serviceId)(ev.service);
17632
17759
  incCount.set(key, (incCount.get(key) ?? 0) + 1);
17633
17760
  }
17634
17761
  const top = [...incCount.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, MAX_FACTS_PER_SECTION);
@@ -17636,7 +17763,7 @@ function buildOverviewSections(graph, incidents) {
17636
17763
  heading: `Nodes with incidents \u2014 ${incidents.length} recorded`,
17637
17764
  facts: top.map(([k, n]) => ({
17638
17765
  text: `${k} \u2014 ${n} incident${n === 1 ? "" : "s"}`,
17639
- provenance: import_types59.Provenance.OBSERVED
17766
+ provenance: import_types61.Provenance.OBSERVED
17640
17767
  }))
17641
17768
  });
17642
17769
  }
@@ -17772,7 +17899,7 @@ async function askGraph(graph, question, opts = {}) {
17772
17899
  const provSet = /* @__PURE__ */ new Set();
17773
17900
  for (const s of sections) for (const f of s.facts) if (f.provenance) provSet.add(f.provenance);
17774
17901
  const confidence = sections[0]?.facts[0]?.confidence;
17775
- return import_types59.AskResultSchema.parse({
17902
+ return import_types61.AskResultSchema.parse({
17776
17903
  question,
17777
17904
  intent,
17778
17905
  matched,
@@ -17865,8 +17992,8 @@ function canonicalJson(value) {
17865
17992
  // src/persist.ts
17866
17993
  init_cjs_shims();
17867
17994
  var import_node_fs36 = require("fs");
17868
- var import_node_path70 = __toESM(require("path"), 1);
17869
- var import_types60 = require("@neat.is/types");
17995
+ var import_node_path71 = __toESM(require("path"), 1);
17996
+ var import_types62 = require("@neat.is/types");
17870
17997
  var SCHEMA_VERSION = 7;
17871
17998
  function migrateV1ToV2(payload) {
17872
17999
  const nodes = payload.graph.nodes;
@@ -17890,7 +18017,7 @@ function migrateV5ToV6(payload) {
17890
18017
  if (Array.isArray(nodes)) {
17891
18018
  for (const node of nodes) {
17892
18019
  const attrs = node.attributes;
17893
- if (!attrs || attrs.type !== import_types60.NodeType.InfraNode) continue;
18020
+ if (!attrs || attrs.type !== import_types62.NodeType.InfraNode) continue;
17894
18021
  if (attrs.kind !== "sql-table" && attrs.kind !== "supabase-table") continue;
17895
18022
  if (!Array.isArray(attrs.columns)) attrs.columns = [];
17896
18023
  }
@@ -17906,12 +18033,12 @@ function migrateV2ToV3(payload) {
17906
18033
  for (const edge of edges) {
17907
18034
  const attrs = edge.attributes;
17908
18035
  if (!attrs || attrs.provenance !== "FRONTIER") continue;
17909
- attrs.provenance = import_types60.Provenance.OBSERVED;
18036
+ attrs.provenance = import_types62.Provenance.OBSERVED;
17910
18037
  const type = typeof attrs.type === "string" ? attrs.type : void 0;
17911
18038
  const source = typeof attrs.source === "string" ? attrs.source : void 0;
17912
18039
  const target = typeof attrs.target === "string" ? attrs.target : void 0;
17913
18040
  if (type && source && target) {
17914
- const newId = (0, import_types60.observedEdgeId)(source, target, type);
18041
+ const newId = (0, import_types62.observedEdgeId)(source, target, type);
17915
18042
  attrs.id = newId;
17916
18043
  if (edge.key) edge.key = newId;
17917
18044
  }
@@ -17920,7 +18047,7 @@ function migrateV2ToV3(payload) {
17920
18047
  return { ...payload, schemaVersion: 3 };
17921
18048
  }
17922
18049
  async function ensureDir(filePath) {
17923
- await import_node_fs36.promises.mkdir(import_node_path70.default.dirname(filePath), { recursive: true });
18050
+ await import_node_fs36.promises.mkdir(import_node_path71.default.dirname(filePath), { recursive: true });
17924
18051
  }
17925
18052
  async function saveGraphToDisk(graph, outPath) {
17926
18053
  await ensureDir(outPath);
@@ -18010,23 +18137,23 @@ function startPersistLoop(graph, outPath, opts = {}) {
18010
18137
 
18011
18138
  // src/projects.ts
18012
18139
  init_cjs_shims();
18013
- var import_node_path71 = __toESM(require("path"), 1);
18140
+ var import_node_path72 = __toESM(require("path"), 1);
18014
18141
  function pathsForProject(project, baseDir) {
18015
18142
  if (project === DEFAULT_PROJECT) {
18016
18143
  return {
18017
- snapshotPath: import_node_path71.default.join(baseDir, "graph.json"),
18018
- errorsPath: import_node_path71.default.join(baseDir, "errors.ndjson"),
18019
- staleEventsPath: import_node_path71.default.join(baseDir, "stale-events.ndjson"),
18020
- embeddingsCachePath: import_node_path71.default.join(baseDir, "embeddings.json"),
18021
- policyViolationsPath: import_node_path71.default.join(baseDir, "policy-violations.ndjson")
18144
+ snapshotPath: import_node_path72.default.join(baseDir, "graph.json"),
18145
+ errorsPath: import_node_path72.default.join(baseDir, "errors.ndjson"),
18146
+ staleEventsPath: import_node_path72.default.join(baseDir, "stale-events.ndjson"),
18147
+ embeddingsCachePath: import_node_path72.default.join(baseDir, "embeddings.json"),
18148
+ policyViolationsPath: import_node_path72.default.join(baseDir, "policy-violations.ndjson")
18022
18149
  };
18023
18150
  }
18024
18151
  return {
18025
- snapshotPath: import_node_path71.default.join(baseDir, `${project}.json`),
18026
- errorsPath: import_node_path71.default.join(baseDir, `errors.${project}.ndjson`),
18027
- staleEventsPath: import_node_path71.default.join(baseDir, `stale-events.${project}.ndjson`),
18028
- embeddingsCachePath: import_node_path71.default.join(baseDir, `embeddings.${project}.json`),
18029
- policyViolationsPath: import_node_path71.default.join(baseDir, `policy-violations.${project}.ndjson`)
18152
+ snapshotPath: import_node_path72.default.join(baseDir, `${project}.json`),
18153
+ errorsPath: import_node_path72.default.join(baseDir, `errors.${project}.ndjson`),
18154
+ staleEventsPath: import_node_path72.default.join(baseDir, `stale-events.${project}.ndjson`),
18155
+ embeddingsCachePath: import_node_path72.default.join(baseDir, `embeddings.${project}.json`),
18156
+ policyViolationsPath: import_node_path72.default.join(baseDir, `policy-violations.${project}.ndjson`)
18030
18157
  };
18031
18158
  }
18032
18159
  var Projects = class {
@@ -18068,18 +18195,18 @@ function parseExtraProjects(raw) {
18068
18195
  init_cjs_shims();
18069
18196
  var import_node_fs37 = require("fs");
18070
18197
  var import_node_os3 = __toESM(require("os"), 1);
18071
- var import_node_path72 = __toESM(require("path"), 1);
18072
- var import_types61 = require("@neat.is/types");
18198
+ var import_node_path73 = __toESM(require("path"), 1);
18199
+ var import_types63 = require("@neat.is/types");
18073
18200
  function neatHome() {
18074
18201
  const override = process.env.NEAT_HOME;
18075
- if (override && override.length > 0) return import_node_path72.default.resolve(override);
18076
- return import_node_path72.default.join(import_node_os3.default.homedir(), ".neat");
18202
+ if (override && override.length > 0) return import_node_path73.default.resolve(override);
18203
+ return import_node_path73.default.join(import_node_os3.default.homedir(), ".neat");
18077
18204
  }
18078
18205
  function registryPath() {
18079
- return import_node_path72.default.join(neatHome(), "projects.json");
18206
+ return import_node_path73.default.join(neatHome(), "projects.json");
18080
18207
  }
18081
18208
  function daemonsDir() {
18082
- return import_node_path72.default.join(neatHome(), "daemons");
18209
+ return import_node_path73.default.join(neatHome(), "daemons");
18083
18210
  }
18084
18211
  function isFiniteInt(v) {
18085
18212
  return typeof v === "number" && Number.isFinite(v);
@@ -18120,7 +18247,7 @@ async function discoverDaemons(probe = defaultDiscoveryProbe) {
18120
18247
  const out = [];
18121
18248
  for (const name of names) {
18122
18249
  if (!name.endsWith(".json")) continue;
18123
- const file = import_node_path72.default.join(dir, name);
18250
+ const file = import_node_path73.default.join(dir, name);
18124
18251
  let raw;
18125
18252
  try {
18126
18253
  raw = await import_node_fs37.promises.readFile(file, "utf8");
@@ -18159,7 +18286,7 @@ async function readRegistry() {
18159
18286
  throw err;
18160
18287
  }
18161
18288
  const parsed = JSON.parse(raw);
18162
- return import_types61.RegistryFileSchema.parse(parsed);
18289
+ return import_types63.RegistryFileSchema.parse(parsed);
18163
18290
  }
18164
18291
  async function getProject(name) {
18165
18292
  const reg = await readRegistry();
@@ -18234,7 +18361,7 @@ init_auth();
18234
18361
  // src/connectors-config.ts
18235
18362
  init_cjs_shims();
18236
18363
  var import_node_os4 = __toESM(require("os"), 1);
18237
- var import_node_path73 = __toESM(require("path"), 1);
18364
+ var import_node_path74 = __toESM(require("path"), 1);
18238
18365
  var import_node_fs38 = require("fs");
18239
18366
  var CONNECTORS_CONFIG_VERSION = 1;
18240
18367
  var EnvRefUnsetError = class extends Error {
@@ -18249,11 +18376,11 @@ var EnvRefUnsetError = class extends Error {
18249
18376
  };
18250
18377
  function neatHome2() {
18251
18378
  const override = process.env.NEAT_HOME;
18252
- if (override && override.length > 0) return import_node_path73.default.resolve(override);
18253
- return import_node_path73.default.join(import_node_os4.default.homedir(), ".neat");
18379
+ if (override && override.length > 0) return import_node_path74.default.resolve(override);
18380
+ return import_node_path74.default.join(import_node_os4.default.homedir(), ".neat");
18254
18381
  }
18255
18382
  function connectorsConfigPath(home = neatHome2()) {
18256
- return import_node_path73.default.join(home, "connectors.json");
18383
+ return import_node_path74.default.join(home, "connectors.json");
18257
18384
  }
18258
18385
  var MODE_MASK_LOOSER_THAN_0600 = 63;
18259
18386
  async function warnIfModeLooserThan0600(file) {
@@ -18440,15 +18567,15 @@ function getConnectorStatus(id, now = Date.now(), thresholdMs = CONNECTOR_STALE_
18440
18567
 
18441
18568
  // src/connectors/index.ts
18442
18569
  init_cjs_shims();
18443
- var import_types62 = require("@neat.is/types");
18570
+ var import_types64 = require("@neat.is/types");
18444
18571
  var NO_ENV = "unknown";
18445
18572
  function staticCallSiteFor(graph, serviceName, targetNodeId) {
18446
18573
  if (!graph.hasNode(targetNodeId)) return void 0;
18447
18574
  const sites = [];
18448
18575
  for (const edgeId of graph.inboundEdges(targetNodeId)) {
18449
18576
  const edge = graph.getEdgeAttributes(edgeId);
18450
- if (edge.provenance !== import_types62.Provenance.EXTRACTED) continue;
18451
- const parsed = (0, import_types62.parseFileId)(edge.source);
18577
+ if (edge.provenance !== import_types64.Provenance.EXTRACTED) continue;
18578
+ const parsed = (0, import_types64.parseFileId)(edge.source);
18452
18579
  if (!parsed || parsed.service !== serviceName || !edge.evidence) continue;
18453
18580
  const site = { relPath: edge.evidence.file };
18454
18581
  if (edge.evidence.line !== void 0) site.line = edge.evidence.line;
@@ -18459,7 +18586,7 @@ function staticCallSiteFor(graph, serviceName, targetNodeId) {
18459
18586
  function routeCallSiteFor(graph, targetNodeId) {
18460
18587
  if (!graph.hasNode(targetNodeId)) return void 0;
18461
18588
  const attrs = graph.getNodeAttributes(targetNodeId);
18462
- if (attrs.type !== import_types62.NodeType.RouteNode || !attrs.path) return void 0;
18589
+ if (attrs.type !== import_types64.NodeType.RouteNode || !attrs.path) return void 0;
18463
18590
  const site = { relPath: attrs.path };
18464
18591
  if (attrs.line !== void 0) site.line = attrs.line;
18465
18592
  return site;
@@ -18916,10 +19043,10 @@ var SUPABASE_RPC_TARGET_KIND = "supabase-rpc";
18916
19043
  // src/connectors/supabase/map.ts
18917
19044
  var REST_RPC_PATH_RE = /^\/rest\/v1\/rpc\/([^/?]+)/;
18918
19045
  var REST_TABLE_PATH_RE = /^\/rest\/v1\/([^/?]+)/;
18919
- function targetFromRestPath(path76) {
18920
- const rpcMatch = REST_RPC_PATH_RE.exec(path76);
19046
+ function targetFromRestPath(path77) {
19047
+ const rpcMatch = REST_RPC_PATH_RE.exec(path77);
18921
19048
  if (rpcMatch) return { targetKind: SUPABASE_RPC_TARGET_KIND, name: rpcMatch[1] };
18922
- const tableMatch = REST_TABLE_PATH_RE.exec(path76);
19049
+ const tableMatch = REST_TABLE_PATH_RE.exec(path77);
18923
19050
  if (tableMatch) return { targetKind: SUPABASE_TABLE_TARGET_KIND, name: tableMatch[1] };
18924
19051
  return null;
18925
19052
  }
@@ -19030,23 +19157,23 @@ async function fetchPgStatStatements(connectionString, limit = DEFAULT_STATEMENT
19030
19157
 
19031
19158
  // src/connectors/supabase/resolve.ts
19032
19159
  init_cjs_shims();
19033
- var import_types64 = require("@neat.is/types");
19160
+ var import_types66 = require("@neat.is/types");
19034
19161
  function createSupabaseResolveTarget(graph, config) {
19035
19162
  return (signal, _ctx) => {
19036
19163
  if (signal.targetKind !== SUPABASE_TABLE_TARGET_KIND && signal.targetKind !== SUPABASE_RPC_TARGET_KIND) {
19037
19164
  return null;
19038
19165
  }
19039
- const subResourceId = (0, import_types64.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
19166
+ const subResourceId = (0, import_types66.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
19040
19167
  if (graph.hasNode(subResourceId)) {
19041
- return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types64.EdgeType.CALLS };
19168
+ return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types66.EdgeType.CALLS };
19042
19169
  }
19043
- const bareResourceId = (0, import_types64.infraId)(signal.targetKind, signal.targetName);
19170
+ const bareResourceId = (0, import_types66.infraId)(signal.targetKind, signal.targetName);
19044
19171
  if (graph.hasNode(bareResourceId)) {
19045
- return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types64.EdgeType.CALLS };
19172
+ return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types66.EdgeType.CALLS };
19046
19173
  }
19047
- const projectLevelId = (0, import_types64.infraId)("supabase", config.nodeRef);
19174
+ const projectLevelId = (0, import_types66.infraId)("supabase", config.nodeRef);
19048
19175
  if (graph.hasNode(projectLevelId)) {
19049
- return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types64.EdgeType.CALLS };
19176
+ return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types66.EdgeType.CALLS };
19050
19177
  }
19051
19178
  return null;
19052
19179
  };
@@ -19139,7 +19266,7 @@ function createSupabaseConnector(graph, config, deps = {}) {
19139
19266
 
19140
19267
  // src/connectors/railway/index.ts
19141
19268
  init_cjs_shims();
19142
- var import_types68 = require("@neat.is/types");
19269
+ var import_types70 = require("@neat.is/types");
19143
19270
 
19144
19271
  // src/connectors/railway/client.ts
19145
19272
  init_cjs_shims();
@@ -19290,7 +19417,7 @@ function buildRailwayRouteIndex(graph, serviceName) {
19290
19417
  const out = [];
19291
19418
  graph.forEachNode((_id, attrs) => {
19292
19419
  const node = attrs;
19293
- if (node.type !== import_types68.NodeType.RouteNode) return;
19420
+ if (node.type !== import_types70.NodeType.RouteNode) return;
19294
19421
  const route = attrs;
19295
19422
  if (route.service !== serviceName) return;
19296
19423
  out.push({
@@ -19394,12 +19521,12 @@ function createRailwayResolveTarget(config) {
19394
19521
  const serviceName = config.serviceNameById[config.serviceId];
19395
19522
  if (!serviceName) return null;
19396
19523
  if (signal.targetKind === ROUTE_TARGET_KIND) {
19397
- return { targetNodeId: signal.targetName, serviceName, edgeType: import_types68.EdgeType.CALLS };
19524
+ return { targetNodeId: signal.targetName, serviceName, edgeType: import_types70.EdgeType.CALLS };
19398
19525
  }
19399
19526
  if (signal.targetKind === PEER_SERVICE_TARGET_KIND) {
19400
19527
  const peerName = config.serviceNameById[signal.targetName];
19401
19528
  if (!peerName) return null;
19402
- return { targetNodeId: (0, import_types68.serviceId)(peerName), serviceName, edgeType: import_types68.EdgeType.CONNECTS_TO };
19529
+ return { targetNodeId: (0, import_types70.serviceId)(peerName), serviceName, edgeType: import_types70.EdgeType.CONNECTS_TO };
19403
19530
  }
19404
19531
  return null;
19405
19532
  };
@@ -19523,9 +19650,9 @@ function parseFirebaseTargetName(targetName) {
19523
19650
  const secondSep = rest.indexOf(FIELD_SEP);
19524
19651
  if (secondSep === -1) return null;
19525
19652
  const method = rest.slice(0, secondSep);
19526
- const path76 = rest.slice(secondSep + 1);
19527
- if (!resourceName || !method || !path76) return null;
19528
- return { resourceName, method, path: path76 };
19653
+ const path77 = rest.slice(secondSep + 1);
19654
+ if (!resourceName || !method || !path77) return null;
19655
+ return { resourceName, method, path: path77 };
19529
19656
  }
19530
19657
  function resourceNameFor(type, labels) {
19531
19658
  if (!labels) return null;
@@ -19563,14 +19690,14 @@ function mapLogEntryToSignal(entry) {
19563
19690
  if (!req) return null;
19564
19691
  if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
19565
19692
  const method = req.requestMethod.toUpperCase();
19566
- const path76 = pathFromRequestUrl(req.requestUrl);
19567
- if (path76 === null) return null;
19693
+ const path77 = pathFromRequestUrl(req.requestUrl);
19694
+ if (path77 === null) return null;
19568
19695
  const timestamp = entry.timestamp;
19569
19696
  if (typeof timestamp !== "string" || timestamp.length === 0) return null;
19570
19697
  const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD2;
19571
19698
  return {
19572
19699
  targetKind: resourceType,
19573
- targetName: packFirebaseTargetName({ resourceName, method, path: path76 }),
19700
+ targetName: packFirebaseTargetName({ resourceName, method, path: path77 }),
19574
19701
  callCount: 1,
19575
19702
  errorCount: isError ? 1 : 0,
19576
19703
  lastObservedIso: timestamp
@@ -19587,7 +19714,7 @@ function mapLogEntriesToSignals(entries) {
19587
19714
 
19588
19715
  // src/connectors/firebase/resolve.ts
19589
19716
  init_cjs_shims();
19590
- var import_types69 = require("@neat.is/types");
19717
+ var import_types71 = require("@neat.is/types");
19591
19718
  function neatServiceNameFor(resourceType, resourceName, serviceMap) {
19592
19719
  switch (resourceType) {
19593
19720
  case "cloud_function":
@@ -19602,7 +19729,7 @@ function routeEntriesFor(graph, serviceName) {
19602
19729
  const entries = [];
19603
19730
  graph.forEachNode((_id, attrs) => {
19604
19731
  const node = attrs;
19605
- if (node.type !== import_types69.NodeType.RouteNode) return;
19732
+ if (node.type !== import_types71.NodeType.RouteNode) return;
19606
19733
  const route = attrs;
19607
19734
  if (route.service !== serviceName) return;
19608
19735
  entries.push({
@@ -19634,7 +19761,7 @@ function createFirebaseResolveTarget(graph, serviceMap) {
19634
19761
  return {
19635
19762
  targetNodeId: match.routeNodeId,
19636
19763
  serviceName,
19637
- edgeType: import_types69.EdgeType.CALLS
19764
+ edgeType: import_types71.EdgeType.CALLS
19638
19765
  };
19639
19766
  };
19640
19767
  }
@@ -19661,7 +19788,7 @@ init_cjs_shims();
19661
19788
 
19662
19789
  // src/connectors/cloudflare/connector.ts
19663
19790
  init_cjs_shims();
19664
- var import_types71 = require("@neat.is/types");
19791
+ var import_types73 = require("@neat.is/types");
19665
19792
 
19666
19793
  // src/connectors/cloudflare/client.ts
19667
19794
  init_cjs_shims();
@@ -19777,7 +19904,7 @@ function mapEventToSignal(event) {
19777
19904
  if (Number.isNaN(observedAt.getTime())) return null;
19778
19905
  const statusCode = metadata?.statusCode;
19779
19906
  const isError = typeof statusCode === "number" && statusCode >= ERROR_STATUS_THRESHOLD3;
19780
- const path76 = metadata?.trigger ? parsePathFromTrigger(metadata.trigger) : void 0;
19907
+ const path77 = metadata?.trigger ? parsePathFromTrigger(metadata.trigger) : void 0;
19781
19908
  return {
19782
19909
  targetKind: CLOUDFLARE_TARGET_KIND,
19783
19910
  targetName: scriptName,
@@ -19785,7 +19912,7 @@ function mapEventToSignal(event) {
19785
19912
  errorCount: isError ? 1 : 0,
19786
19913
  lastObservedIso: observedAt.toISOString(),
19787
19914
  method,
19788
- ...path76 ? { path: path76 } : {},
19915
+ ...path77 ? { path: path77 } : {},
19789
19916
  ...typeof statusCode === "number" ? { statusCode } : {},
19790
19917
  ...typeof metadata?.duration === "number" ? { duration: metadata.duration } : {}
19791
19918
  };
@@ -19825,19 +19952,19 @@ function findTaggedWorkerFileNode(graph, workerName) {
19825
19952
  graph.forEachNode((id, attrs) => {
19826
19953
  if (found) return;
19827
19954
  const a = attrs;
19828
- if (a.type === import_types71.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
19955
+ if (a.type === import_types73.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
19829
19956
  found = id;
19830
19957
  }
19831
19958
  });
19832
19959
  return found;
19833
19960
  }
19834
- function findMatchingRouteNode(graph, serviceName, method, path76) {
19835
- const normalizedPath = normalizePathTemplate(path76);
19961
+ function findMatchingRouteNode(graph, serviceName, method, path77) {
19962
+ const normalizedPath = normalizePathTemplate(path77);
19836
19963
  let found = null;
19837
19964
  graph.forEachNode((id, attrs) => {
19838
19965
  if (found) return;
19839
19966
  const a = attrs;
19840
- if (a.type !== import_types71.NodeType.RouteNode || a.service !== serviceName) return;
19967
+ if (a.type !== import_types73.NodeType.RouteNode || a.service !== serviceName) return;
19841
19968
  if (!a.pathTemplate || normalizePathTemplate(a.pathTemplate) !== normalizedPath) return;
19842
19969
  const routeMethod = (a.method ?? "").toUpperCase();
19843
19970
  if (routeMethod !== "ALL" && routeMethod !== method) return;
@@ -19849,18 +19976,18 @@ function createCloudflareResolveTarget(config, graph) {
19849
19976
  return (signal) => {
19850
19977
  if (signal.targetKind !== CLOUDFLARE_TARGET_KIND) return null;
19851
19978
  const scriptName = signal.targetName;
19852
- const { method, path: path76 } = signal;
19979
+ const { method, path: path77 } = signal;
19853
19980
  const resolveRouteGrain = (serviceName, wholeFileId) => {
19854
- if (!method || !path76) return wholeFileId;
19855
- return findMatchingRouteNode(graph, serviceName, method, path76) ?? wholeFileId;
19981
+ if (!method || !path77) return wholeFileId;
19982
+ return findMatchingRouteNode(graph, serviceName, method, path77) ?? wholeFileId;
19856
19983
  };
19857
19984
  const mapping = config.workers?.[scriptName];
19858
19985
  if (mapping) {
19859
- const wholeFileId = (0, import_types71.fileId)(mapping.service, mapping.entryFile);
19986
+ const wholeFileId = (0, import_types73.fileId)(mapping.service, mapping.entryFile);
19860
19987
  return {
19861
19988
  targetNodeId: resolveRouteGrain(mapping.service, wholeFileId),
19862
19989
  serviceName: mapping.service,
19863
- edgeType: import_types71.EdgeType.CALLS
19990
+ edgeType: import_types73.EdgeType.CALLS
19864
19991
  };
19865
19992
  }
19866
19993
  const taggedFileId = findTaggedWorkerFileNode(graph, scriptName);
@@ -19869,13 +19996,13 @@ function createCloudflareResolveTarget(config, graph) {
19869
19996
  return {
19870
19997
  targetNodeId: resolveRouteGrain(fileNode.service, taggedFileId),
19871
19998
  serviceName: fileNode.service,
19872
- edgeType: import_types71.EdgeType.CALLS
19999
+ edgeType: import_types73.EdgeType.CALLS
19873
20000
  };
19874
20001
  }
19875
20002
  return {
19876
- targetNodeId: (0, import_types71.infraId)("cloudflare-worker", scriptName),
20003
+ targetNodeId: (0, import_types73.infraId)("cloudflare-worker", scriptName),
19877
20004
  serviceName: scriptName,
19878
- edgeType: import_types71.EdgeType.CALLS,
20005
+ edgeType: import_types73.EdgeType.CALLS,
19879
20006
  ensureInfraNode: { kind: "cloudflare-worker", name: scriptName, provider: "cloudflare" }
19880
20007
  };
19881
20008
  };
@@ -20071,14 +20198,14 @@ function diffNeonStatementsToSignals(rows, previous, observedAtIso) {
20071
20198
 
20072
20199
  // src/connectors/neon/resolve.ts
20073
20200
  init_cjs_shims();
20074
- var import_types75 = require("@neat.is/types");
20201
+ var import_types77 = require("@neat.is/types");
20075
20202
  function createNeonResolveTarget(config) {
20076
20203
  return (signal) => {
20077
20204
  if (signal.targetKind !== NEON_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
20078
20205
  return {
20079
- targetNodeId: (0, import_types75.infraId)("sql-table", signal.targetName),
20206
+ targetNodeId: (0, import_types77.infraId)("sql-table", signal.targetName),
20080
20207
  serviceName: config.serviceName,
20081
- edgeType: import_types75.EdgeType.CALLS,
20208
+ edgeType: import_types77.EdgeType.CALLS,
20082
20209
  ensureInfraNode: { kind: "sql-table", name: signal.targetName, provider: "neon" }
20083
20210
  };
20084
20211
  };
@@ -20204,9 +20331,9 @@ function parseCloudRunTargetName(targetName) {
20204
20331
  const secondSep = rest.indexOf(FIELD_SEP2);
20205
20332
  if (secondSep === -1) return null;
20206
20333
  const method = rest.slice(0, secondSep);
20207
- const path76 = rest.slice(secondSep + 1);
20208
- if (!serviceName || !method || !path76) return null;
20209
- return { serviceName, method, path: path76 };
20334
+ const path77 = rest.slice(secondSep + 1);
20335
+ if (!serviceName || !method || !path77) return null;
20336
+ return { serviceName, method, path: path77 };
20210
20337
  }
20211
20338
 
20212
20339
  // src/connectors/cloud-run/map.ts
@@ -20235,14 +20362,14 @@ function mapLogEntryToSignal2(entry) {
20235
20362
  if (!req) return null;
20236
20363
  if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
20237
20364
  const method = req.requestMethod.toUpperCase();
20238
- const path76 = pathFromRequestUrl2(req.requestUrl);
20239
- if (path76 === null) return null;
20365
+ const path77 = pathFromRequestUrl2(req.requestUrl);
20366
+ if (path77 === null) return null;
20240
20367
  const timestamp = entry.timestamp;
20241
20368
  if (typeof timestamp !== "string" || timestamp.length === 0) return null;
20242
20369
  const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD4;
20243
20370
  return {
20244
20371
  targetKind: CLOUD_RUN_TARGET_KIND,
20245
- targetName: packCloudRunTargetName({ serviceName, method, path: path76 }),
20372
+ targetName: packCloudRunTargetName({ serviceName, method, path: path77 }),
20246
20373
  callCount: 1,
20247
20374
  errorCount: isError ? 1 : 0,
20248
20375
  lastObservedIso: timestamp
@@ -20259,14 +20386,14 @@ function mapLogEntriesToSignals2(entries) {
20259
20386
 
20260
20387
  // src/connectors/cloud-run/resolve.ts
20261
20388
  init_cjs_shims();
20262
- var import_types79 = require("@neat.is/types");
20389
+ var import_types81 = require("@neat.is/types");
20263
20390
  var CLOUD_RUN_SERVICE_INFRA_KIND = "cloud-run-service";
20264
20391
  function findMatchingRouteNode2(graph, serviceName, method, normalizedPath) {
20265
20392
  let found = null;
20266
20393
  graph.forEachNode((_id, attrs) => {
20267
20394
  if (found) return;
20268
20395
  const node = attrs;
20269
- if (node.type !== import_types79.NodeType.RouteNode) return;
20396
+ if (node.type !== import_types81.NodeType.RouteNode) return;
20270
20397
  const route = attrs;
20271
20398
  if (route.service !== serviceName || !route.pathTemplate) return;
20272
20399
  if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
@@ -20281,23 +20408,23 @@ function createCloudRunResolveTarget(graph, config) {
20281
20408
  if (signal.targetKind !== CLOUD_RUN_TARGET_KIND) return null;
20282
20409
  const identity = parseCloudRunTargetName(signal.targetName);
20283
20410
  if (!identity) return null;
20284
- const { serviceName: gcpServiceName, method, path: path76 } = identity;
20411
+ const { serviceName: gcpServiceName, method, path: path77 } = identity;
20285
20412
  const mappedService = config.serviceMap?.[gcpServiceName];
20286
20413
  if (mappedService) {
20287
20414
  const routeNodeId = findMatchingRouteNode2(
20288
20415
  graph,
20289
20416
  mappedService,
20290
20417
  method,
20291
- normalizePathTemplate(path76)
20418
+ normalizePathTemplate(path77)
20292
20419
  );
20293
20420
  if (routeNodeId) {
20294
- return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types79.EdgeType.CALLS };
20421
+ return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types81.EdgeType.CALLS };
20295
20422
  }
20296
20423
  }
20297
20424
  return {
20298
- targetNodeId: (0, import_types79.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
20425
+ targetNodeId: (0, import_types81.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
20299
20426
  serviceName: mappedService ?? gcpServiceName,
20300
- edgeType: import_types79.EdgeType.CALLS,
20427
+ edgeType: import_types81.EdgeType.CALLS,
20301
20428
  ensureInfraNode: {
20302
20429
  kind: CLOUD_RUN_SERVICE_INFRA_KIND,
20303
20430
  name: gcpServiceName,
@@ -20424,9 +20551,9 @@ function parseGcpLbTargetName(targetName) {
20424
20551
  const secondSep = rest.indexOf(FIELD_SEP3);
20425
20552
  if (secondSep === -1) return null;
20426
20553
  const method = rest.slice(0, secondSep);
20427
- const path76 = rest.slice(secondSep + 1);
20428
- if (!backendServiceName || !method || !path76) return null;
20429
- return { backendServiceName, method, path: path76 };
20554
+ const path77 = rest.slice(secondSep + 1);
20555
+ if (!backendServiceName || !method || !path77) return null;
20556
+ return { backendServiceName, method, path: path77 };
20430
20557
  }
20431
20558
 
20432
20559
  // src/connectors/gcp-lb/map.ts
@@ -20455,14 +20582,14 @@ function mapLogEntryToSignal3(entry) {
20455
20582
  if (!req) return null;
20456
20583
  if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
20457
20584
  const method = req.requestMethod.toUpperCase();
20458
- const path76 = pathFromRequestUrl3(req.requestUrl);
20459
- if (path76 === null) return null;
20585
+ const path77 = pathFromRequestUrl3(req.requestUrl);
20586
+ if (path77 === null) return null;
20460
20587
  const timestamp = entry.timestamp;
20461
20588
  if (typeof timestamp !== "string" || timestamp.length === 0) return null;
20462
20589
  const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD5;
20463
20590
  return {
20464
20591
  targetKind: GCP_LB_TARGET_KIND,
20465
- targetName: packGcpLbTargetName({ backendServiceName, method, path: path76 }),
20592
+ targetName: packGcpLbTargetName({ backendServiceName, method, path: path77 }),
20466
20593
  callCount: 1,
20467
20594
  errorCount: isError ? 1 : 0,
20468
20595
  lastObservedIso: timestamp
@@ -20479,14 +20606,14 @@ function mapLogEntriesToSignals3(entries) {
20479
20606
 
20480
20607
  // src/connectors/gcp-lb/resolve.ts
20481
20608
  init_cjs_shims();
20482
- var import_types83 = require("@neat.is/types");
20609
+ var import_types85 = require("@neat.is/types");
20483
20610
  var GCP_LB_BACKEND_INFRA_KIND = "gcp-lb-backend";
20484
20611
  function findMatchingRouteNode3(graph, serviceName, method, normalizedPath) {
20485
20612
  let found = null;
20486
20613
  graph.forEachNode((_id, attrs) => {
20487
20614
  if (found) return;
20488
20615
  const node = attrs;
20489
- if (node.type !== import_types83.NodeType.RouteNode) return;
20616
+ if (node.type !== import_types85.NodeType.RouteNode) return;
20490
20617
  const route = attrs;
20491
20618
  if (route.service !== serviceName || !route.pathTemplate) return;
20492
20619
  if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
@@ -20501,23 +20628,23 @@ function createGcpLbResolveTarget(graph, config) {
20501
20628
  if (signal.targetKind !== GCP_LB_TARGET_KIND) return null;
20502
20629
  const identity = parseGcpLbTargetName(signal.targetName);
20503
20630
  if (!identity) return null;
20504
- const { backendServiceName, method, path: path76 } = identity;
20631
+ const { backendServiceName, method, path: path77 } = identity;
20505
20632
  const mappedService = config.backendServiceMap?.[backendServiceName];
20506
20633
  if (mappedService) {
20507
20634
  const routeNodeId = findMatchingRouteNode3(
20508
20635
  graph,
20509
20636
  mappedService,
20510
20637
  method,
20511
- normalizePathTemplate(path76)
20638
+ normalizePathTemplate(path77)
20512
20639
  );
20513
20640
  if (routeNodeId) {
20514
- return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types83.EdgeType.CALLS };
20641
+ return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types85.EdgeType.CALLS };
20515
20642
  }
20516
20643
  }
20517
20644
  return {
20518
- targetNodeId: (0, import_types83.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
20645
+ targetNodeId: (0, import_types85.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
20519
20646
  serviceName: mappedService ?? backendServiceName,
20520
- edgeType: import_types83.EdgeType.CALLS,
20647
+ edgeType: import_types85.EdgeType.CALLS,
20521
20648
  ensureInfraNode: {
20522
20649
  kind: GCP_LB_BACKEND_INFRA_KIND,
20523
20650
  name: backendServiceName,
@@ -20558,7 +20685,7 @@ function createGcpLbConnector(graph, config = {}) {
20558
20685
 
20559
20686
  // src/connectors/render/index.ts
20560
20687
  init_cjs_shims();
20561
- var import_types86 = require("@neat.is/types");
20688
+ var import_types88 = require("@neat.is/types");
20562
20689
 
20563
20690
  // src/connectors/render/types.ts
20564
20691
  init_cjs_shims();
@@ -20636,7 +20763,7 @@ function buildRenderRouteIndex(graph, serviceName) {
20636
20763
  const out = [];
20637
20764
  graph.forEachNode((_id, attrs) => {
20638
20765
  const node = attrs;
20639
- if (node.type !== import_types86.NodeType.RouteNode) return;
20766
+ if (node.type !== import_types88.NodeType.RouteNode) return;
20640
20767
  const route = attrs;
20641
20768
  if (route.service !== serviceName) return;
20642
20769
  out.push({
@@ -20721,7 +20848,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
20721
20848
  function createRenderResolveTarget(config) {
20722
20849
  return (signal) => {
20723
20850
  if (signal.targetKind === ROUTE_TARGET_KIND2) {
20724
- return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types86.EdgeType.CALLS };
20851
+ return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types88.EdgeType.CALLS };
20725
20852
  }
20726
20853
  return null;
20727
20854
  };
@@ -20859,21 +20986,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
20859
20986
 
20860
20987
  // src/connectors/planetscale/resolve.ts
20861
20988
  init_cjs_shims();
20862
- var import_types90 = require("@neat.is/types");
20989
+ var import_types92 = require("@neat.is/types");
20863
20990
  var PLANETSCALE_DATABASE_KIND = "planetscale-database";
20864
20991
  function createPlanetscaleResolveTarget(graph, config) {
20865
20992
  const databaseName = `${config.organization}/${config.database}`;
20866
20993
  return (signal, _ctx) => {
20867
20994
  if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
20868
- const tableId = (0, import_types90.infraId)("sql-table", signal.targetName);
20995
+ const tableId = (0, import_types92.infraId)("sql-table", signal.targetName);
20869
20996
  if (graph.hasNode(tableId)) {
20870
- return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types90.EdgeType.CALLS };
20997
+ return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types92.EdgeType.CALLS };
20871
20998
  }
20872
- const providerId = (0, import_types90.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
20999
+ const providerId = (0, import_types92.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
20873
21000
  return {
20874
21001
  targetNodeId: providerId,
20875
21002
  serviceName: config.serviceName,
20876
- edgeType: import_types90.EdgeType.CALLS,
21003
+ edgeType: import_types92.EdgeType.CALLS,
20877
21004
  ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
20878
21005
  };
20879
21006
  };
@@ -21138,7 +21265,7 @@ function mapBuildsToSignals(builds, serviceName) {
21138
21265
 
21139
21266
  // src/connectors/eas/resolve.ts
21140
21267
  init_cjs_shims();
21141
- var import_types95 = require("@neat.is/types");
21268
+ var import_types97 = require("@neat.is/types");
21142
21269
  var NO_ENV2 = "unknown";
21143
21270
  var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
21144
21271
  var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
@@ -21154,8 +21281,8 @@ function configBasenamesForPhase(phase) {
21154
21281
  function configNodeService(graph, configNodeId) {
21155
21282
  for (const edgeId of graph.inboundEdges(configNodeId)) {
21156
21283
  const edge = graph.getEdgeAttributes(edgeId);
21157
- if (edge.type !== import_types95.EdgeType.CONFIGURED_BY) continue;
21158
- const parsed = (0, import_types95.parseFileId)(edge.source);
21284
+ if (edge.type !== import_types97.EdgeType.CONFIGURED_BY) continue;
21285
+ const parsed = (0, import_types97.parseFileId)(edge.source);
21159
21286
  if (parsed) return parsed.service;
21160
21287
  }
21161
21288
  return null;
@@ -21166,7 +21293,7 @@ function findConfigNode(graph, basenames, serviceName) {
21166
21293
  graph.forEachNode((id, attrs) => {
21167
21294
  if (scoped) return;
21168
21295
  const node = attrs;
21169
- if (node.type !== import_types95.NodeType.ConfigNode) return;
21296
+ if (node.type !== import_types97.NodeType.ConfigNode) return;
21170
21297
  if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
21171
21298
  if (anyMatch === null) anyMatch = id;
21172
21299
  if (configNodeService(graph, id) === serviceName) scoped = id;
@@ -21183,13 +21310,13 @@ function createEasResolveTarget(graph) {
21183
21310
  if (basenames.length > 0) {
21184
21311
  const configNodeId = findConfigNode(graph, basenames, serviceName);
21185
21312
  if (configNodeId) {
21186
- return { targetNodeId: configNodeId, serviceName, edgeType: import_types95.EdgeType.CALLS };
21313
+ return { targetNodeId: configNodeId, serviceName, edgeType: import_types97.EdgeType.CALLS };
21187
21314
  }
21188
21315
  }
21189
21316
  return {
21190
21317
  targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV2),
21191
21318
  serviceName,
21192
- edgeType: import_types95.EdgeType.CALLS
21319
+ edgeType: import_types97.EdgeType.CALLS
21193
21320
  };
21194
21321
  };
21195
21322
  }
@@ -21904,11 +22031,11 @@ function registerRoutes(scope, ctx) {
21904
22031
  const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
21905
22032
  const parsed = [];
21906
22033
  for (const c of candidates) {
21907
- const r = import_types98.DivergenceTypeSchema.safeParse(c);
22034
+ const r = import_types100.DivergenceTypeSchema.safeParse(c);
21908
22035
  if (!r.success) {
21909
22036
  return reply.code(400).send({
21910
22037
  error: `unknown divergence type "${c}"`,
21911
- allowed: import_types98.DivergenceTypeSchema.options
22038
+ allowed: import_types100.DivergenceTypeSchema.options
21912
22039
  });
21913
22040
  }
21914
22041
  parsed.push(r.data);
@@ -22304,7 +22431,7 @@ function registerRoutes(scope, ctx) {
22304
22431
  const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
22305
22432
  let violations = await log.readAll();
22306
22433
  if (req.query.severity) {
22307
- const sev = import_types98.PolicySeveritySchema.safeParse(req.query.severity);
22434
+ const sev = import_types100.PolicySeveritySchema.safeParse(req.query.severity);
22308
22435
  if (!sev.success) {
22309
22436
  return reply.code(400).send({
22310
22437
  error: "invalid severity",
@@ -22343,7 +22470,7 @@ function registerRoutes(scope, ctx) {
22343
22470
  scope.post("/policies/check", async (req, reply) => {
22344
22471
  const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
22345
22472
  if (!proj) return;
22346
- const parsed = import_types98.PoliciesCheckBodySchema.safeParse(req.body ?? {});
22473
+ const parsed = import_types100.PoliciesCheckBodySchema.safeParse(req.body ?? {});
22347
22474
  if (!parsed.success) {
22348
22475
  return reply.code(400).send({
22349
22476
  error: "invalid /policies/check body",
@@ -22665,7 +22792,7 @@ init_otel_grpc();
22665
22792
  // src/search.ts
22666
22793
  init_cjs_shims();
22667
22794
  var import_node_fs39 = require("fs");
22668
- var import_node_path74 = __toESM(require("path"), 1);
22795
+ var import_node_path75 = __toESM(require("path"), 1);
22669
22796
  var import_node_crypto4 = require("crypto");
22670
22797
  var DEFAULT_LIMIT = 10;
22671
22798
  var NOMIC_DIM = 768;
@@ -22828,7 +22955,7 @@ async function readCache(cachePath) {
22828
22955
  }
22829
22956
  }
22830
22957
  async function writeCache(cachePath, cache) {
22831
- await import_node_fs39.promises.mkdir(import_node_path74.default.dirname(cachePath), { recursive: true });
22958
+ await import_node_fs39.promises.mkdir(import_node_path75.default.dirname(cachePath), { recursive: true });
22832
22959
  await import_node_fs39.promises.writeFile(cachePath, JSON.stringify(cache));
22833
22960
  }
22834
22961
  var VectorIndex = class {
@@ -23043,14 +23170,14 @@ async function bootProject(registry, name, scanPath, baseDir) {
23043
23170
  async function main() {
23044
23171
  const baseDirEnv = process.env.NEAT_OUT_DIR;
23045
23172
  const legacyOutPath = process.env.NEAT_OUT_PATH;
23046
- const baseDir = baseDirEnv ? import_node_path75.default.resolve(baseDirEnv) : legacyOutPath ? import_node_path75.default.resolve(import_node_path75.default.dirname(legacyOutPath)) : import_node_path75.default.resolve("./neat-out");
23047
- const defaultScanPath = import_node_path75.default.resolve(process.env.NEAT_SCAN_PATH ?? "./demo");
23173
+ const baseDir = baseDirEnv ? import_node_path76.default.resolve(baseDirEnv) : legacyOutPath ? import_node_path76.default.resolve(import_node_path76.default.dirname(legacyOutPath)) : import_node_path76.default.resolve("./neat-out");
23174
+ const defaultScanPath = import_node_path76.default.resolve(process.env.NEAT_SCAN_PATH ?? "./demo");
23048
23175
  const registry = new Projects();
23049
23176
  await bootProject(registry, DEFAULT_PROJECT, defaultScanPath, baseDir);
23050
23177
  for (const name of parseExtraProjects(process.env.NEAT_PROJECTS)) {
23051
23178
  const envKey = `NEAT_PROJECT_SCAN_PATH_${name.toUpperCase().replace(/[^A-Z0-9]/g, "_")}`;
23052
23179
  const projectScan = process.env[envKey];
23053
- await bootProject(registry, name, projectScan ? import_node_path75.default.resolve(projectScan) : void 0, baseDir);
23180
+ await bootProject(registry, name, projectScan ? import_node_path76.default.resolve(projectScan) : void 0, baseDir);
23054
23181
  }
23055
23182
  const host = process.env.HOST ?? "0.0.0.0";
23056
23183
  const port = Number(process.env.PORT ?? 8080);