@neat.is/core 0.9.8-dev.20260829 → 0.9.9
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/{chunk-KZBFP7L6.js → chunk-B6KJG5KN.js} +219 -13
- package/dist/chunk-B6KJG5KN.js.map +1 -0
- package/dist/{chunk-JSUPWMH3.js → chunk-QETJIA2Q.js} +14 -4
- package/dist/{chunk-JSUPWMH3.js.map → chunk-QETJIA2Q.js.map} +1 -1
- package/dist/cli.cjs +343 -98
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +46 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +294 -82
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +294 -82
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +280 -80
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-KZBFP7L6.js.map +0 -1
package/dist/server.cjs
CHANGED
|
@@ -787,7 +787,7 @@ function getGraph(project = DEFAULT_PROJECT) {
|
|
|
787
787
|
init_cjs_shims();
|
|
788
788
|
var import_fastify2 = __toESM(require("fastify"), 1);
|
|
789
789
|
var import_cors = __toESM(require("@fastify/cors"), 1);
|
|
790
|
-
var
|
|
790
|
+
var import_types98 = require("@neat.is/types");
|
|
791
791
|
|
|
792
792
|
// src/extend/index.ts
|
|
793
793
|
init_cjs_shims();
|
|
@@ -5596,11 +5596,25 @@ function upsertInferredEdge(graph, type, source, target, ts) {
|
|
|
5596
5596
|
};
|
|
5597
5597
|
graph.addEdgeWithKey(id, source, target, edge);
|
|
5598
5598
|
}
|
|
5599
|
+
function emitIncidentEvent(project, ev) {
|
|
5600
|
+
emitNeatEvent({
|
|
5601
|
+
type: "incident",
|
|
5602
|
+
project,
|
|
5603
|
+
payload: {
|
|
5604
|
+
incidentId: ev.id,
|
|
5605
|
+
affectedNode: ev.affectedNode,
|
|
5606
|
+
service: ev.service,
|
|
5607
|
+
incidentKind: (0, import_types7.incidentKindOf)(ev),
|
|
5608
|
+
at: ev.timestamp
|
|
5609
|
+
}
|
|
5610
|
+
});
|
|
5611
|
+
}
|
|
5599
5612
|
async function appendErrorEvent(ctx, ev) {
|
|
5600
5613
|
await import_node_fs9.promises.mkdir(import_node_path10.default.dirname(ctx.errorsPath), { recursive: true });
|
|
5601
5614
|
await import_node_fs9.promises.appendFile(ctx.errorsPath, JSON.stringify(ev) + "\n", "utf8");
|
|
5615
|
+
emitIncidentEvent(ctx.project ?? DEFAULT_PROJECT, ev);
|
|
5602
5616
|
}
|
|
5603
|
-
async function appendConnectorIncident(errorsPath, input) {
|
|
5617
|
+
async function appendConnectorIncident(errorsPath, input, project) {
|
|
5604
5618
|
const ev = {
|
|
5605
5619
|
id: input.id,
|
|
5606
5620
|
timestamp: input.timestamp,
|
|
@@ -5614,6 +5628,7 @@ async function appendConnectorIncident(errorsPath, input) {
|
|
|
5614
5628
|
};
|
|
5615
5629
|
await import_node_fs9.promises.mkdir(import_node_path10.default.dirname(errorsPath), { recursive: true });
|
|
5616
5630
|
await import_node_fs9.promises.appendFile(errorsPath, JSON.stringify(ev) + "\n", "utf8");
|
|
5631
|
+
if (project) emitIncidentEvent(project, ev);
|
|
5617
5632
|
}
|
|
5618
5633
|
function landIncidentCallSite(span, callSite, trusted, graph) {
|
|
5619
5634
|
const relPath = graph ? reconcileObservedRelPath(graph, span.service, callSite.relPath) : callSite.relPath;
|
|
@@ -16867,9 +16882,160 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
16867
16882
|
return result;
|
|
16868
16883
|
}
|
|
16869
16884
|
|
|
16870
|
-
// src/
|
|
16885
|
+
// src/goodybag.ts
|
|
16871
16886
|
init_cjs_shims();
|
|
16872
16887
|
var import_types58 = require("@neat.is/types");
|
|
16888
|
+
var CODE_FILEPATH_ATTR2 = "code.filepath";
|
|
16889
|
+
var CODE_LINENO_ATTR2 = "code.lineno";
|
|
16890
|
+
var BLAST_NEAREST_LIMIT = 5;
|
|
16891
|
+
function grainOf2(graph, nodeId) {
|
|
16892
|
+
if (graph.hasNode(nodeId)) {
|
|
16893
|
+
const t = graph.getNodeAttributes(nodeId).type;
|
|
16894
|
+
if (typeof t === "string" && t.length > 0) {
|
|
16895
|
+
return (t.endsWith("Node") ? t.slice(0, -4) : t).toLowerCase();
|
|
16896
|
+
}
|
|
16897
|
+
}
|
|
16898
|
+
const colon = nodeId.indexOf(":");
|
|
16899
|
+
return colon > 0 ? nodeId.slice(0, colon) : "unknown";
|
|
16900
|
+
}
|
|
16901
|
+
function locusOf(graph, ev) {
|
|
16902
|
+
const file = ev.attributes?.[CODE_FILEPATH_ATTR2];
|
|
16903
|
+
if (typeof file !== "string" || file.length === 0) return null;
|
|
16904
|
+
const rawLine = ev.attributes?.[CODE_LINENO_ATTR2];
|
|
16905
|
+
const line = typeof rawLine === "number" ? rawLine : Number(rawLine);
|
|
16906
|
+
const node = graph.hasNode(ev.affectedNode) ? graph.getNodeAttributes(ev.affectedNode) : void 0;
|
|
16907
|
+
return {
|
|
16908
|
+
file,
|
|
16909
|
+
...Number.isFinite(line) ? { lineStart: line, lineEnd: line } : {},
|
|
16910
|
+
...node?.name ? { symbol: node.name } : {},
|
|
16911
|
+
service: node?.service ?? ev.service,
|
|
16912
|
+
provenance: import_types58.Provenance.OBSERVED
|
|
16913
|
+
};
|
|
16914
|
+
}
|
|
16915
|
+
function locusFromNode(graph, nodeId) {
|
|
16916
|
+
if (!graph.hasNode(nodeId)) return null;
|
|
16917
|
+
const n = graph.getNodeAttributes(nodeId);
|
|
16918
|
+
const file = n.relPath ?? n.path;
|
|
16919
|
+
if (typeof file !== "string" || file.length === 0) return null;
|
|
16920
|
+
const start = n.span?.startLine;
|
|
16921
|
+
const end = n.span?.endLine;
|
|
16922
|
+
return {
|
|
16923
|
+
file,
|
|
16924
|
+
...typeof start === "number" ? { lineStart: start } : {},
|
|
16925
|
+
...typeof end === "number" ? { lineEnd: end } : {},
|
|
16926
|
+
...n.qualname ? { symbol: shortLabel(graph, nodeId) } : {},
|
|
16927
|
+
...n.service ? { service: n.service } : {},
|
|
16928
|
+
provenance: import_types58.Provenance.INFERRED
|
|
16929
|
+
};
|
|
16930
|
+
}
|
|
16931
|
+
function promoteCauseLocus(graph, causeNode, incidents) {
|
|
16932
|
+
const native = incidents.find(
|
|
16933
|
+
(e) => e.affectedNode === causeNode && typeof e.attributes?.[CODE_FILEPATH_ATTR2] === "string"
|
|
16934
|
+
);
|
|
16935
|
+
if (native) {
|
|
16936
|
+
const l = locusOf(graph, native);
|
|
16937
|
+
if (l) return { ...l, symbol: shortLabel(graph, causeNode), provenance: import_types58.Provenance.INFERRED };
|
|
16938
|
+
}
|
|
16939
|
+
return locusFromNode(graph, causeNode);
|
|
16940
|
+
}
|
|
16941
|
+
function divergenceSummary(d) {
|
|
16942
|
+
const column = "column" in d && d.column ? `.${d.column}` : "";
|
|
16943
|
+
const label = "table" in d && d.table ? `${d.table}${column}` : `${d.source} \u2192 ${d.target}`;
|
|
16944
|
+
return label;
|
|
16945
|
+
}
|
|
16946
|
+
function baseName(p) {
|
|
16947
|
+
const parts = p.split(/[\\/]/);
|
|
16948
|
+
return parts[parts.length - 1] || p;
|
|
16949
|
+
}
|
|
16950
|
+
function shortLabel(graph, nodeId) {
|
|
16951
|
+
if (graph.hasNode(nodeId)) {
|
|
16952
|
+
const name = graph.getNodeAttributes(nodeId).name;
|
|
16953
|
+
if (typeof name === "string" && name.length > 0) return name;
|
|
16954
|
+
}
|
|
16955
|
+
const afterHash = nodeId.includes("#") ? nodeId.slice(nodeId.lastIndexOf("#") + 1) : nodeId;
|
|
16956
|
+
return afterHash.includes(":") ? afterHash.slice(afterHash.lastIndexOf(":") + 1) : afterHash;
|
|
16957
|
+
}
|
|
16958
|
+
function renderHeadline(graph, ev, locus, causeNode) {
|
|
16959
|
+
const what = ev.exceptionType ? `raised ${ev.exceptionType}` : ev.errorMessage || "failed";
|
|
16960
|
+
const causeLabel = causeNode && causeNode !== ev.affectedNode ? shortLabel(graph, causeNode) : "";
|
|
16961
|
+
if (locus) {
|
|
16962
|
+
const base = baseName(locus.file);
|
|
16963
|
+
const lines = locus.lineStart != null ? locus.lineEnd && locus.lineEnd !== locus.lineStart ? `LINES ${locus.lineStart}-${locus.lineEnd}` : `LINE ${locus.lineStart}` : "";
|
|
16964
|
+
const symbol = locus.symbol ?? (grainOf2(graph, ev.affectedNode) === "symbol" ? shortLabel(graph, ev.affectedNode) : void 0);
|
|
16965
|
+
const subject = symbol ? `SYMBOL ${symbol}` : `FILE ${base}`;
|
|
16966
|
+
const at = symbol ? `${lines ? `${lines} in ` : ""}${base}` : lines;
|
|
16967
|
+
const where = at ? ` at ${at}` : "";
|
|
16968
|
+
const svc = locus.service ?? ev.service;
|
|
16969
|
+
const cause2 = causeLabel && causeLabel !== symbol ? ` \u2192 root cause ${causeLabel}` : "";
|
|
16970
|
+
return `${subject}${where} (SERVICE ${svc}) ${what} at ${ev.timestamp}${cause2}`;
|
|
16971
|
+
}
|
|
16972
|
+
const cause = causeLabel ? ` \u2192 root cause ${causeLabel}` : "";
|
|
16973
|
+
return `SERVICE ${ev.service} ${what} at ${ev.timestamp}${cause}`;
|
|
16974
|
+
}
|
|
16975
|
+
function buildIncidentCard(graph, errorEvent, incidents, policies) {
|
|
16976
|
+
const affected = errorEvent.affectedNode;
|
|
16977
|
+
let locus = locusOf(graph, errorEvent);
|
|
16978
|
+
const inGraph = graph.hasNode(affected);
|
|
16979
|
+
const rc = inGraph ? getRootCause(graph, affected, errorEvent, incidents) : null;
|
|
16980
|
+
let rootCause = null;
|
|
16981
|
+
if (rc) {
|
|
16982
|
+
const provs = rc.edgeProvenances ?? [];
|
|
16983
|
+
const chain = (rc.traversalPath ?? []).map((node, i) => ({
|
|
16984
|
+
node,
|
|
16985
|
+
grain: grainOf2(graph, node),
|
|
16986
|
+
provenance: provs[i] ?? provs[provs.length - 1] ?? import_types58.Provenance.INFERRED
|
|
16987
|
+
}));
|
|
16988
|
+
rootCause = {
|
|
16989
|
+
node: rc.rootCauseNode,
|
|
16990
|
+
...rc.candidates?.[0]?.classification ? { classification: rc.candidates[0].classification } : {},
|
|
16991
|
+
reason: rc.rootCauseReason,
|
|
16992
|
+
confidence: rc.confidence,
|
|
16993
|
+
fix: rc.fixRecommendation ?? null,
|
|
16994
|
+
chain
|
|
16995
|
+
};
|
|
16996
|
+
}
|
|
16997
|
+
if (locus === null && rootCause) {
|
|
16998
|
+
locus = promoteCauseLocus(graph, rootCause.node, incidents);
|
|
16999
|
+
}
|
|
17000
|
+
const blast = inGraph ? getBlastRadius(graph, affected) : { origin: affected, affectedNodes: [], totalAffected: 0 };
|
|
17001
|
+
const nearest = [...blast.affectedNodes].sort((a, b) => a.distance - b.distance).slice(0, BLAST_NEAREST_LIMIT).map((n) => ({ node: n.nodeId, distance: n.distance, provenance: n.edgeProvenance }));
|
|
17002
|
+
const applicable = inGraph ? selectApplicablePolicies(graph, policies, affected) : [];
|
|
17003
|
+
const policyCards = applicable.map((p) => ({
|
|
17004
|
+
policyName: p.policyName,
|
|
17005
|
+
severity: p.severity,
|
|
17006
|
+
message: p.reason
|
|
17007
|
+
}));
|
|
17008
|
+
const divergences = inGraph ? computeDivergences(graph, { node: affected, incidents }).divergences.map((d) => ({
|
|
17009
|
+
type: d.type,
|
|
17010
|
+
summary: divergenceSummary(d)
|
|
17011
|
+
})) : [];
|
|
17012
|
+
const card = {
|
|
17013
|
+
kind: "incident",
|
|
17014
|
+
id: errorEvent.id,
|
|
17015
|
+
at: errorEvent.timestamp,
|
|
17016
|
+
incidentKind: (0, import_types58.incidentKindOf)(errorEvent),
|
|
17017
|
+
service: errorEvent.service,
|
|
17018
|
+
affectedNode: affected,
|
|
17019
|
+
message: errorEvent.errorMessage,
|
|
17020
|
+
...errorEvent.exceptionType ? { exceptionType: errorEvent.exceptionType } : {},
|
|
17021
|
+
...errorEvent.httpStatusCode !== void 0 ? { httpStatusCode: errorEvent.httpStatusCode } : {},
|
|
17022
|
+
...errorEvent.incidentCount !== void 0 ? { count: errorEvent.incidentCount } : {},
|
|
17023
|
+
...errorEvent.firstTimestamp && errorEvent.lastTimestamp ? { window: { first: errorEvent.firstTimestamp, last: errorEvent.lastTimestamp } } : {},
|
|
17024
|
+
...errorEvent.traceId ? { traceId: errorEvent.traceId } : {},
|
|
17025
|
+
...errorEvent.spanId ? { spanId: errorEvent.spanId } : {},
|
|
17026
|
+
locus,
|
|
17027
|
+
rootCause,
|
|
17028
|
+
...nearest.length > 0 ? { blastRadius: { totalAffected: blast.totalAffected, nearest } } : {},
|
|
17029
|
+
...policyCards.length > 0 ? { policies: policyCards } : {},
|
|
17030
|
+
...divergences.length > 0 ? { divergence: divergences } : {},
|
|
17031
|
+
headline: renderHeadline(graph, errorEvent, locus, rootCause?.node ?? null)
|
|
17032
|
+
};
|
|
17033
|
+
return import_types58.IncidentCardSchema.parse(card);
|
|
17034
|
+
}
|
|
17035
|
+
|
|
17036
|
+
// src/ask.ts
|
|
17037
|
+
init_cjs_shims();
|
|
17038
|
+
var import_types59 = require("@neat.is/types");
|
|
16873
17039
|
var DEFAULT_MAX_NODES = 3;
|
|
16874
17040
|
var MAX_FACTS_PER_SECTION = 6;
|
|
16875
17041
|
var INTENT_RULES = [
|
|
@@ -17097,7 +17263,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
|
|
|
17097
17263
|
};
|
|
17098
17264
|
graph.forEachNode((id, attrs) => {
|
|
17099
17265
|
const node = attrs;
|
|
17100
|
-
if (node.type ===
|
|
17266
|
+
if (node.type === import_types59.NodeType.FrontierNode) return;
|
|
17101
17267
|
const name = nodeName(node);
|
|
17102
17268
|
const body = idBody(id);
|
|
17103
17269
|
const labelTokens = /* @__PURE__ */ new Set([...tokens(body), ...tokens(name)]);
|
|
@@ -17116,7 +17282,7 @@ async function resolveEntities(graph, question, searchIndex, maxNodes) {
|
|
|
17116
17282
|
const res = await searchIndex.search(question, 10);
|
|
17117
17283
|
if (res.provider !== "substring") {
|
|
17118
17284
|
for (const m of res.matches) {
|
|
17119
|
-
if (m.node.type ===
|
|
17285
|
+
if (m.node.type === import_types59.NodeType.FrontierNode) continue;
|
|
17120
17286
|
const already = best.get(m.node.id);
|
|
17121
17287
|
if (!already && m.score < EMBED_MIN_SCORE) continue;
|
|
17122
17288
|
consider({
|
|
@@ -17154,7 +17320,7 @@ function edgeSignalNote(e) {
|
|
|
17154
17320
|
function buildRootCauseSection(graph, node, incidents, now) {
|
|
17155
17321
|
const result = getRootCause(graph, node, void 0, incidents, { now });
|
|
17156
17322
|
if (!result) return null;
|
|
17157
|
-
const lastProv = result.edgeProvenances[result.edgeProvenances.length - 1] ??
|
|
17323
|
+
const lastProv = result.edgeProvenances[result.edgeProvenances.length - 1] ?? import_types59.Provenance.OBSERVED;
|
|
17158
17324
|
const facts = [
|
|
17159
17325
|
{
|
|
17160
17326
|
text: `Root cause: ${result.rootCauseNode} \u2014 ${result.rootCauseReason}`,
|
|
@@ -17204,7 +17370,7 @@ function buildObservedSection(graph, node) {
|
|
|
17204
17370
|
if (result.observed && result.inboundObservedCount > 0) {
|
|
17205
17371
|
facts.push({
|
|
17206
17372
|
text: `no outbound runtime calls, but OTel observed ${result.inboundObservedCount} inbound call path${result.inboundObservedCount === 1 ? "" : "s"} \u2014 a pure receiver`,
|
|
17207
|
-
provenance:
|
|
17373
|
+
provenance: import_types59.Provenance.OBSERVED
|
|
17208
17374
|
});
|
|
17209
17375
|
} else {
|
|
17210
17376
|
return null;
|
|
@@ -17232,7 +17398,7 @@ function buildIncidentsSection(node, incidents) {
|
|
|
17232
17398
|
const facts = ordered.map((ev) => ({
|
|
17233
17399
|
text: `${ev.timestamp} \u2014 ${ev.service}: ${ev.errorMessage}`,
|
|
17234
17400
|
// ErrorEvents are observation records — OBSERVED by definition.
|
|
17235
|
-
provenance:
|
|
17401
|
+
provenance: import_types59.Provenance.OBSERVED
|
|
17236
17402
|
}));
|
|
17237
17403
|
return { heading: `Recent incidents (OBSERVED) \u2014 ${relevant.length} recorded`, facts };
|
|
17238
17404
|
}
|
|
@@ -17292,7 +17458,7 @@ function buildGlobalIncidentsSection(incidents) {
|
|
|
17292
17458
|
}
|
|
17293
17459
|
const byKey = /* @__PURE__ */ new Map();
|
|
17294
17460
|
for (const ev of incidents) {
|
|
17295
|
-
const key = ev.affectedNode || (0,
|
|
17461
|
+
const key = ev.affectedNode || (0, import_types59.serviceId)(ev.service);
|
|
17296
17462
|
const cur = byKey.get(key);
|
|
17297
17463
|
if (!cur) {
|
|
17298
17464
|
byKey.set(key, { key, count: 1, latest: ev.timestamp, sampleMsg: ev.errorMessage });
|
|
@@ -17307,7 +17473,7 @@ function buildGlobalIncidentsSection(incidents) {
|
|
|
17307
17473
|
const rows = [...byKey.values()].sort((a, b) => b.count - a.count || b.latest.localeCompare(a.latest) || a.key.localeCompare(b.key)).slice(0, MAX_FACTS_PER_SECTION);
|
|
17308
17474
|
const facts = rows.map((r) => ({
|
|
17309
17475
|
text: `${r.key} \u2014 ${r.count} incident${r.count === 1 ? "" : "s"}, latest ${r.latest}: ${r.sampleMsg}`,
|
|
17310
|
-
provenance:
|
|
17476
|
+
provenance: import_types59.Provenance.OBSERVED
|
|
17311
17477
|
}));
|
|
17312
17478
|
return {
|
|
17313
17479
|
heading: `Incidents across the system \u2014 ${incidents.length} recorded`,
|
|
@@ -17320,7 +17486,7 @@ function buildOverviewSections(graph, incidents) {
|
|
|
17320
17486
|
graph.forEachNode((_id, attrs) => {
|
|
17321
17487
|
const node = attrs;
|
|
17322
17488
|
nodeByType.set(node.type, (nodeByType.get(node.type) ?? 0) + 1);
|
|
17323
|
-
if (node.type ===
|
|
17489
|
+
if (node.type === import_types59.NodeType.ServiceNode) services.push(node.id);
|
|
17324
17490
|
});
|
|
17325
17491
|
const edgeByProv = /* @__PURE__ */ new Map();
|
|
17326
17492
|
graph.forEachEdge((_id, attrs) => {
|
|
@@ -17332,10 +17498,10 @@ function buildOverviewSections(graph, incidents) {
|
|
|
17332
17498
|
const shapeFacts = [
|
|
17333
17499
|
{ text: `${graph.order} nodes, ${graph.size} edges` },
|
|
17334
17500
|
{
|
|
17335
|
-
text: `${count(
|
|
17501
|
+
text: `${count(import_types59.NodeType.ServiceNode)} services, ${count(import_types59.NodeType.FileNode)} files, ${count(import_types59.NodeType.SymbolNode)} symbols, ${count(import_types59.NodeType.DatabaseNode)} databases`
|
|
17336
17502
|
}
|
|
17337
17503
|
];
|
|
17338
|
-
for (const p of [
|
|
17504
|
+
for (const p of [import_types59.Provenance.EXTRACTED, import_types59.Provenance.OBSERVED, import_types59.Provenance.INFERRED, import_types59.Provenance.STALE]) {
|
|
17339
17505
|
const n = edgeByProv.get(p) ?? 0;
|
|
17340
17506
|
if (n > 0) shapeFacts.push({ text: `${n} ${p} edge${n === 1 ? "" : "s"}`, provenance: p });
|
|
17341
17507
|
}
|
|
@@ -17352,7 +17518,7 @@ function buildOverviewSections(graph, incidents) {
|
|
|
17352
17518
|
if (incidents && incidents.length > 0) {
|
|
17353
17519
|
const incCount = /* @__PURE__ */ new Map();
|
|
17354
17520
|
for (const ev of incidents) {
|
|
17355
|
-
const key = ev.affectedNode || (0,
|
|
17521
|
+
const key = ev.affectedNode || (0, import_types59.serviceId)(ev.service);
|
|
17356
17522
|
incCount.set(key, (incCount.get(key) ?? 0) + 1);
|
|
17357
17523
|
}
|
|
17358
17524
|
const top = [...incCount.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, MAX_FACTS_PER_SECTION);
|
|
@@ -17360,7 +17526,7 @@ function buildOverviewSections(graph, incidents) {
|
|
|
17360
17526
|
heading: `Nodes with incidents \u2014 ${incidents.length} recorded`,
|
|
17361
17527
|
facts: top.map(([k, n]) => ({
|
|
17362
17528
|
text: `${k} \u2014 ${n} incident${n === 1 ? "" : "s"}`,
|
|
17363
|
-
provenance:
|
|
17529
|
+
provenance: import_types59.Provenance.OBSERVED
|
|
17364
17530
|
}))
|
|
17365
17531
|
});
|
|
17366
17532
|
}
|
|
@@ -17496,7 +17662,7 @@ async function askGraph(graph, question, opts = {}) {
|
|
|
17496
17662
|
const provSet = /* @__PURE__ */ new Set();
|
|
17497
17663
|
for (const s of sections) for (const f of s.facts) if (f.provenance) provSet.add(f.provenance);
|
|
17498
17664
|
const confidence = sections[0]?.facts[0]?.confidence;
|
|
17499
|
-
return
|
|
17665
|
+
return import_types59.AskResultSchema.parse({
|
|
17500
17666
|
question,
|
|
17501
17667
|
intent,
|
|
17502
17668
|
matched,
|
|
@@ -17590,7 +17756,7 @@ function canonicalJson(value) {
|
|
|
17590
17756
|
init_cjs_shims();
|
|
17591
17757
|
var import_node_fs36 = require("fs");
|
|
17592
17758
|
var import_node_path70 = __toESM(require("path"), 1);
|
|
17593
|
-
var
|
|
17759
|
+
var import_types60 = require("@neat.is/types");
|
|
17594
17760
|
var SCHEMA_VERSION = 7;
|
|
17595
17761
|
function migrateV1ToV2(payload) {
|
|
17596
17762
|
const nodes = payload.graph.nodes;
|
|
@@ -17614,7 +17780,7 @@ function migrateV5ToV6(payload) {
|
|
|
17614
17780
|
if (Array.isArray(nodes)) {
|
|
17615
17781
|
for (const node of nodes) {
|
|
17616
17782
|
const attrs = node.attributes;
|
|
17617
|
-
if (!attrs || attrs.type !==
|
|
17783
|
+
if (!attrs || attrs.type !== import_types60.NodeType.InfraNode) continue;
|
|
17618
17784
|
if (attrs.kind !== "sql-table" && attrs.kind !== "supabase-table") continue;
|
|
17619
17785
|
if (!Array.isArray(attrs.columns)) attrs.columns = [];
|
|
17620
17786
|
}
|
|
@@ -17630,12 +17796,12 @@ function migrateV2ToV3(payload) {
|
|
|
17630
17796
|
for (const edge of edges) {
|
|
17631
17797
|
const attrs = edge.attributes;
|
|
17632
17798
|
if (!attrs || attrs.provenance !== "FRONTIER") continue;
|
|
17633
|
-
attrs.provenance =
|
|
17799
|
+
attrs.provenance = import_types60.Provenance.OBSERVED;
|
|
17634
17800
|
const type = typeof attrs.type === "string" ? attrs.type : void 0;
|
|
17635
17801
|
const source = typeof attrs.source === "string" ? attrs.source : void 0;
|
|
17636
17802
|
const target = typeof attrs.target === "string" ? attrs.target : void 0;
|
|
17637
17803
|
if (type && source && target) {
|
|
17638
|
-
const newId = (0,
|
|
17804
|
+
const newId = (0, import_types60.observedEdgeId)(source, target, type);
|
|
17639
17805
|
attrs.id = newId;
|
|
17640
17806
|
if (edge.key) edge.key = newId;
|
|
17641
17807
|
}
|
|
@@ -17793,7 +17959,7 @@ init_cjs_shims();
|
|
|
17793
17959
|
var import_node_fs37 = require("fs");
|
|
17794
17960
|
var import_node_os3 = __toESM(require("os"), 1);
|
|
17795
17961
|
var import_node_path72 = __toESM(require("path"), 1);
|
|
17796
|
-
var
|
|
17962
|
+
var import_types61 = require("@neat.is/types");
|
|
17797
17963
|
function neatHome() {
|
|
17798
17964
|
const override = process.env.NEAT_HOME;
|
|
17799
17965
|
if (override && override.length > 0) return import_node_path72.default.resolve(override);
|
|
@@ -17883,7 +18049,7 @@ async function readRegistry() {
|
|
|
17883
18049
|
throw err;
|
|
17884
18050
|
}
|
|
17885
18051
|
const parsed = JSON.parse(raw);
|
|
17886
|
-
return
|
|
18052
|
+
return import_types61.RegistryFileSchema.parse(parsed);
|
|
17887
18053
|
}
|
|
17888
18054
|
async function getProject(name) {
|
|
17889
18055
|
const reg = await readRegistry();
|
|
@@ -18164,15 +18330,15 @@ function getConnectorStatus(id, now = Date.now(), thresholdMs = CONNECTOR_STALE_
|
|
|
18164
18330
|
|
|
18165
18331
|
// src/connectors/index.ts
|
|
18166
18332
|
init_cjs_shims();
|
|
18167
|
-
var
|
|
18333
|
+
var import_types62 = require("@neat.is/types");
|
|
18168
18334
|
var NO_ENV = "unknown";
|
|
18169
18335
|
function staticCallSiteFor(graph, serviceName, targetNodeId) {
|
|
18170
18336
|
if (!graph.hasNode(targetNodeId)) return void 0;
|
|
18171
18337
|
const sites = [];
|
|
18172
18338
|
for (const edgeId of graph.inboundEdges(targetNodeId)) {
|
|
18173
18339
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
18174
|
-
if (edge.provenance !==
|
|
18175
|
-
const parsed = (0,
|
|
18340
|
+
if (edge.provenance !== import_types62.Provenance.EXTRACTED) continue;
|
|
18341
|
+
const parsed = (0, import_types62.parseFileId)(edge.source);
|
|
18176
18342
|
if (!parsed || parsed.service !== serviceName || !edge.evidence) continue;
|
|
18177
18343
|
const site = { relPath: edge.evidence.file };
|
|
18178
18344
|
if (edge.evidence.line !== void 0) site.line = edge.evidence.line;
|
|
@@ -18183,7 +18349,7 @@ function staticCallSiteFor(graph, serviceName, targetNodeId) {
|
|
|
18183
18349
|
function routeCallSiteFor(graph, targetNodeId) {
|
|
18184
18350
|
if (!graph.hasNode(targetNodeId)) return void 0;
|
|
18185
18351
|
const attrs = graph.getNodeAttributes(targetNodeId);
|
|
18186
|
-
if (attrs.type !==
|
|
18352
|
+
if (attrs.type !== import_types62.NodeType.RouteNode || !attrs.path) return void 0;
|
|
18187
18353
|
const site = { relPath: attrs.path };
|
|
18188
18354
|
if (attrs.line !== void 0) site.line = attrs.line;
|
|
18189
18355
|
return site;
|
|
@@ -18213,7 +18379,7 @@ async function runConnectorPoll(connector, ctx, graph, resolveTarget) {
|
|
|
18213
18379
|
errorMessage: signal.incident.errorMessage,
|
|
18214
18380
|
...signal.incident.attributes ? { attributes: signal.incident.attributes } : {},
|
|
18215
18381
|
affectedNode: resolved.targetNodeId
|
|
18216
|
-
});
|
|
18382
|
+
}, ctx.project);
|
|
18217
18383
|
continue;
|
|
18218
18384
|
}
|
|
18219
18385
|
if (resolved.ensureInfraNode) {
|
|
@@ -18754,23 +18920,23 @@ async function fetchPgStatStatements(connectionString, limit = DEFAULT_STATEMENT
|
|
|
18754
18920
|
|
|
18755
18921
|
// src/connectors/supabase/resolve.ts
|
|
18756
18922
|
init_cjs_shims();
|
|
18757
|
-
var
|
|
18923
|
+
var import_types64 = require("@neat.is/types");
|
|
18758
18924
|
function createSupabaseResolveTarget(graph, config) {
|
|
18759
18925
|
return (signal, _ctx) => {
|
|
18760
18926
|
if (signal.targetKind !== SUPABASE_TABLE_TARGET_KIND && signal.targetKind !== SUPABASE_RPC_TARGET_KIND) {
|
|
18761
18927
|
return null;
|
|
18762
18928
|
}
|
|
18763
|
-
const subResourceId = (0,
|
|
18929
|
+
const subResourceId = (0, import_types64.infraId)(signal.targetKind, `${config.nodeRef}/${signal.targetName}`);
|
|
18764
18930
|
if (graph.hasNode(subResourceId)) {
|
|
18765
|
-
return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType:
|
|
18931
|
+
return { targetNodeId: subResourceId, serviceName: config.serviceName, edgeType: import_types64.EdgeType.CALLS };
|
|
18766
18932
|
}
|
|
18767
|
-
const bareResourceId = (0,
|
|
18933
|
+
const bareResourceId = (0, import_types64.infraId)(signal.targetKind, signal.targetName);
|
|
18768
18934
|
if (graph.hasNode(bareResourceId)) {
|
|
18769
|
-
return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType:
|
|
18935
|
+
return { targetNodeId: bareResourceId, serviceName: config.serviceName, edgeType: import_types64.EdgeType.CALLS };
|
|
18770
18936
|
}
|
|
18771
|
-
const projectLevelId = (0,
|
|
18937
|
+
const projectLevelId = (0, import_types64.infraId)("supabase", config.nodeRef);
|
|
18772
18938
|
if (graph.hasNode(projectLevelId)) {
|
|
18773
|
-
return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType:
|
|
18939
|
+
return { targetNodeId: projectLevelId, serviceName: config.serviceName, edgeType: import_types64.EdgeType.CALLS };
|
|
18774
18940
|
}
|
|
18775
18941
|
return null;
|
|
18776
18942
|
};
|
|
@@ -18863,7 +19029,7 @@ function createSupabaseConnector(graph, config, deps = {}) {
|
|
|
18863
19029
|
|
|
18864
19030
|
// src/connectors/railway/index.ts
|
|
18865
19031
|
init_cjs_shims();
|
|
18866
|
-
var
|
|
19032
|
+
var import_types68 = require("@neat.is/types");
|
|
18867
19033
|
|
|
18868
19034
|
// src/connectors/railway/client.ts
|
|
18869
19035
|
init_cjs_shims();
|
|
@@ -19014,7 +19180,7 @@ function buildRailwayRouteIndex(graph, serviceName) {
|
|
|
19014
19180
|
const out = [];
|
|
19015
19181
|
graph.forEachNode((_id, attrs) => {
|
|
19016
19182
|
const node = attrs;
|
|
19017
|
-
if (node.type !==
|
|
19183
|
+
if (node.type !== import_types68.NodeType.RouteNode) return;
|
|
19018
19184
|
const route = attrs;
|
|
19019
19185
|
if (route.service !== serviceName) return;
|
|
19020
19186
|
out.push({
|
|
@@ -19118,12 +19284,12 @@ function createRailwayResolveTarget(config) {
|
|
|
19118
19284
|
const serviceName = config.serviceNameById[config.serviceId];
|
|
19119
19285
|
if (!serviceName) return null;
|
|
19120
19286
|
if (signal.targetKind === ROUTE_TARGET_KIND) {
|
|
19121
|
-
return { targetNodeId: signal.targetName, serviceName, edgeType:
|
|
19287
|
+
return { targetNodeId: signal.targetName, serviceName, edgeType: import_types68.EdgeType.CALLS };
|
|
19122
19288
|
}
|
|
19123
19289
|
if (signal.targetKind === PEER_SERVICE_TARGET_KIND) {
|
|
19124
19290
|
const peerName = config.serviceNameById[signal.targetName];
|
|
19125
19291
|
if (!peerName) return null;
|
|
19126
|
-
return { targetNodeId: (0,
|
|
19292
|
+
return { targetNodeId: (0, import_types68.serviceId)(peerName), serviceName, edgeType: import_types68.EdgeType.CONNECTS_TO };
|
|
19127
19293
|
}
|
|
19128
19294
|
return null;
|
|
19129
19295
|
};
|
|
@@ -19311,7 +19477,7 @@ function mapLogEntriesToSignals(entries) {
|
|
|
19311
19477
|
|
|
19312
19478
|
// src/connectors/firebase/resolve.ts
|
|
19313
19479
|
init_cjs_shims();
|
|
19314
|
-
var
|
|
19480
|
+
var import_types69 = require("@neat.is/types");
|
|
19315
19481
|
function neatServiceNameFor(resourceType, resourceName, serviceMap) {
|
|
19316
19482
|
switch (resourceType) {
|
|
19317
19483
|
case "cloud_function":
|
|
@@ -19326,7 +19492,7 @@ function routeEntriesFor(graph, serviceName) {
|
|
|
19326
19492
|
const entries = [];
|
|
19327
19493
|
graph.forEachNode((_id, attrs) => {
|
|
19328
19494
|
const node = attrs;
|
|
19329
|
-
if (node.type !==
|
|
19495
|
+
if (node.type !== import_types69.NodeType.RouteNode) return;
|
|
19330
19496
|
const route = attrs;
|
|
19331
19497
|
if (route.service !== serviceName) return;
|
|
19332
19498
|
entries.push({
|
|
@@ -19358,7 +19524,7 @@ function createFirebaseResolveTarget(graph, serviceMap) {
|
|
|
19358
19524
|
return {
|
|
19359
19525
|
targetNodeId: match.routeNodeId,
|
|
19360
19526
|
serviceName,
|
|
19361
|
-
edgeType:
|
|
19527
|
+
edgeType: import_types69.EdgeType.CALLS
|
|
19362
19528
|
};
|
|
19363
19529
|
};
|
|
19364
19530
|
}
|
|
@@ -19385,7 +19551,7 @@ init_cjs_shims();
|
|
|
19385
19551
|
|
|
19386
19552
|
// src/connectors/cloudflare/connector.ts
|
|
19387
19553
|
init_cjs_shims();
|
|
19388
|
-
var
|
|
19554
|
+
var import_types71 = require("@neat.is/types");
|
|
19389
19555
|
|
|
19390
19556
|
// src/connectors/cloudflare/client.ts
|
|
19391
19557
|
init_cjs_shims();
|
|
@@ -19549,7 +19715,7 @@ function findTaggedWorkerFileNode(graph, workerName) {
|
|
|
19549
19715
|
graph.forEachNode((id, attrs) => {
|
|
19550
19716
|
if (found) return;
|
|
19551
19717
|
const a = attrs;
|
|
19552
|
-
if (a.type ===
|
|
19718
|
+
if (a.type === import_types71.NodeType.FileNode && a.platform === "cloudflare" && a.platformName === workerName) {
|
|
19553
19719
|
found = id;
|
|
19554
19720
|
}
|
|
19555
19721
|
});
|
|
@@ -19561,7 +19727,7 @@ function findMatchingRouteNode(graph, serviceName, method, path76) {
|
|
|
19561
19727
|
graph.forEachNode((id, attrs) => {
|
|
19562
19728
|
if (found) return;
|
|
19563
19729
|
const a = attrs;
|
|
19564
|
-
if (a.type !==
|
|
19730
|
+
if (a.type !== import_types71.NodeType.RouteNode || a.service !== serviceName) return;
|
|
19565
19731
|
if (!a.pathTemplate || normalizePathTemplate(a.pathTemplate) !== normalizedPath) return;
|
|
19566
19732
|
const routeMethod = (a.method ?? "").toUpperCase();
|
|
19567
19733
|
if (routeMethod !== "ALL" && routeMethod !== method) return;
|
|
@@ -19580,11 +19746,11 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
19580
19746
|
};
|
|
19581
19747
|
const mapping = config.workers?.[scriptName];
|
|
19582
19748
|
if (mapping) {
|
|
19583
|
-
const wholeFileId = (0,
|
|
19749
|
+
const wholeFileId = (0, import_types71.fileId)(mapping.service, mapping.entryFile);
|
|
19584
19750
|
return {
|
|
19585
19751
|
targetNodeId: resolveRouteGrain(mapping.service, wholeFileId),
|
|
19586
19752
|
serviceName: mapping.service,
|
|
19587
|
-
edgeType:
|
|
19753
|
+
edgeType: import_types71.EdgeType.CALLS
|
|
19588
19754
|
};
|
|
19589
19755
|
}
|
|
19590
19756
|
const taggedFileId = findTaggedWorkerFileNode(graph, scriptName);
|
|
@@ -19593,13 +19759,13 @@ function createCloudflareResolveTarget(config, graph) {
|
|
|
19593
19759
|
return {
|
|
19594
19760
|
targetNodeId: resolveRouteGrain(fileNode.service, taggedFileId),
|
|
19595
19761
|
serviceName: fileNode.service,
|
|
19596
|
-
edgeType:
|
|
19762
|
+
edgeType: import_types71.EdgeType.CALLS
|
|
19597
19763
|
};
|
|
19598
19764
|
}
|
|
19599
19765
|
return {
|
|
19600
|
-
targetNodeId: (0,
|
|
19766
|
+
targetNodeId: (0, import_types71.infraId)("cloudflare-worker", scriptName),
|
|
19601
19767
|
serviceName: scriptName,
|
|
19602
|
-
edgeType:
|
|
19768
|
+
edgeType: import_types71.EdgeType.CALLS,
|
|
19603
19769
|
ensureInfraNode: { kind: "cloudflare-worker", name: scriptName, provider: "cloudflare" }
|
|
19604
19770
|
};
|
|
19605
19771
|
};
|
|
@@ -19795,14 +19961,14 @@ function diffNeonStatementsToSignals(rows, previous, observedAtIso) {
|
|
|
19795
19961
|
|
|
19796
19962
|
// src/connectors/neon/resolve.ts
|
|
19797
19963
|
init_cjs_shims();
|
|
19798
|
-
var
|
|
19964
|
+
var import_types75 = require("@neat.is/types");
|
|
19799
19965
|
function createNeonResolveTarget(config) {
|
|
19800
19966
|
return (signal) => {
|
|
19801
19967
|
if (signal.targetKind !== NEON_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
19802
19968
|
return {
|
|
19803
|
-
targetNodeId: (0,
|
|
19969
|
+
targetNodeId: (0, import_types75.infraId)("sql-table", signal.targetName),
|
|
19804
19970
|
serviceName: config.serviceName,
|
|
19805
|
-
edgeType:
|
|
19971
|
+
edgeType: import_types75.EdgeType.CALLS,
|
|
19806
19972
|
ensureInfraNode: { kind: "sql-table", name: signal.targetName, provider: "neon" }
|
|
19807
19973
|
};
|
|
19808
19974
|
};
|
|
@@ -19983,14 +20149,14 @@ function mapLogEntriesToSignals2(entries) {
|
|
|
19983
20149
|
|
|
19984
20150
|
// src/connectors/cloud-run/resolve.ts
|
|
19985
20151
|
init_cjs_shims();
|
|
19986
|
-
var
|
|
20152
|
+
var import_types79 = require("@neat.is/types");
|
|
19987
20153
|
var CLOUD_RUN_SERVICE_INFRA_KIND = "cloud-run-service";
|
|
19988
20154
|
function findMatchingRouteNode2(graph, serviceName, method, normalizedPath) {
|
|
19989
20155
|
let found = null;
|
|
19990
20156
|
graph.forEachNode((_id, attrs) => {
|
|
19991
20157
|
if (found) return;
|
|
19992
20158
|
const node = attrs;
|
|
19993
|
-
if (node.type !==
|
|
20159
|
+
if (node.type !== import_types79.NodeType.RouteNode) return;
|
|
19994
20160
|
const route = attrs;
|
|
19995
20161
|
if (route.service !== serviceName || !route.pathTemplate) return;
|
|
19996
20162
|
if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
|
|
@@ -20015,13 +20181,13 @@ function createCloudRunResolveTarget(graph, config) {
|
|
|
20015
20181
|
normalizePathTemplate(path76)
|
|
20016
20182
|
);
|
|
20017
20183
|
if (routeNodeId) {
|
|
20018
|
-
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType:
|
|
20184
|
+
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types79.EdgeType.CALLS };
|
|
20019
20185
|
}
|
|
20020
20186
|
}
|
|
20021
20187
|
return {
|
|
20022
|
-
targetNodeId: (0,
|
|
20188
|
+
targetNodeId: (0, import_types79.infraId)(CLOUD_RUN_SERVICE_INFRA_KIND, gcpServiceName),
|
|
20023
20189
|
serviceName: mappedService ?? gcpServiceName,
|
|
20024
|
-
edgeType:
|
|
20190
|
+
edgeType: import_types79.EdgeType.CALLS,
|
|
20025
20191
|
ensureInfraNode: {
|
|
20026
20192
|
kind: CLOUD_RUN_SERVICE_INFRA_KIND,
|
|
20027
20193
|
name: gcpServiceName,
|
|
@@ -20203,14 +20369,14 @@ function mapLogEntriesToSignals3(entries) {
|
|
|
20203
20369
|
|
|
20204
20370
|
// src/connectors/gcp-lb/resolve.ts
|
|
20205
20371
|
init_cjs_shims();
|
|
20206
|
-
var
|
|
20372
|
+
var import_types83 = require("@neat.is/types");
|
|
20207
20373
|
var GCP_LB_BACKEND_INFRA_KIND = "gcp-lb-backend";
|
|
20208
20374
|
function findMatchingRouteNode3(graph, serviceName, method, normalizedPath) {
|
|
20209
20375
|
let found = null;
|
|
20210
20376
|
graph.forEachNode((_id, attrs) => {
|
|
20211
20377
|
if (found) return;
|
|
20212
20378
|
const node = attrs;
|
|
20213
|
-
if (node.type !==
|
|
20379
|
+
if (node.type !== import_types83.NodeType.RouteNode) return;
|
|
20214
20380
|
const route = attrs;
|
|
20215
20381
|
if (route.service !== serviceName || !route.pathTemplate) return;
|
|
20216
20382
|
if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
|
|
@@ -20235,13 +20401,13 @@ function createGcpLbResolveTarget(graph, config) {
|
|
|
20235
20401
|
normalizePathTemplate(path76)
|
|
20236
20402
|
);
|
|
20237
20403
|
if (routeNodeId) {
|
|
20238
|
-
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType:
|
|
20404
|
+
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types83.EdgeType.CALLS };
|
|
20239
20405
|
}
|
|
20240
20406
|
}
|
|
20241
20407
|
return {
|
|
20242
|
-
targetNodeId: (0,
|
|
20408
|
+
targetNodeId: (0, import_types83.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
|
|
20243
20409
|
serviceName: mappedService ?? backendServiceName,
|
|
20244
|
-
edgeType:
|
|
20410
|
+
edgeType: import_types83.EdgeType.CALLS,
|
|
20245
20411
|
ensureInfraNode: {
|
|
20246
20412
|
kind: GCP_LB_BACKEND_INFRA_KIND,
|
|
20247
20413
|
name: backendServiceName,
|
|
@@ -20282,7 +20448,7 @@ function createGcpLbConnector(graph, config = {}) {
|
|
|
20282
20448
|
|
|
20283
20449
|
// src/connectors/render/index.ts
|
|
20284
20450
|
init_cjs_shims();
|
|
20285
|
-
var
|
|
20451
|
+
var import_types86 = require("@neat.is/types");
|
|
20286
20452
|
|
|
20287
20453
|
// src/connectors/render/types.ts
|
|
20288
20454
|
init_cjs_shims();
|
|
@@ -20360,7 +20526,7 @@ function buildRenderRouteIndex(graph, serviceName) {
|
|
|
20360
20526
|
const out = [];
|
|
20361
20527
|
graph.forEachNode((_id, attrs) => {
|
|
20362
20528
|
const node = attrs;
|
|
20363
|
-
if (node.type !==
|
|
20529
|
+
if (node.type !== import_types86.NodeType.RouteNode) return;
|
|
20364
20530
|
const route = attrs;
|
|
20365
20531
|
if (route.service !== serviceName) return;
|
|
20366
20532
|
out.push({
|
|
@@ -20445,7 +20611,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
|
|
|
20445
20611
|
function createRenderResolveTarget(config) {
|
|
20446
20612
|
return (signal) => {
|
|
20447
20613
|
if (signal.targetKind === ROUTE_TARGET_KIND2) {
|
|
20448
|
-
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType:
|
|
20614
|
+
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types86.EdgeType.CALLS };
|
|
20449
20615
|
}
|
|
20450
20616
|
return null;
|
|
20451
20617
|
};
|
|
@@ -20583,21 +20749,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
|
|
|
20583
20749
|
|
|
20584
20750
|
// src/connectors/planetscale/resolve.ts
|
|
20585
20751
|
init_cjs_shims();
|
|
20586
|
-
var
|
|
20752
|
+
var import_types90 = require("@neat.is/types");
|
|
20587
20753
|
var PLANETSCALE_DATABASE_KIND = "planetscale-database";
|
|
20588
20754
|
function createPlanetscaleResolveTarget(graph, config) {
|
|
20589
20755
|
const databaseName = `${config.organization}/${config.database}`;
|
|
20590
20756
|
return (signal, _ctx) => {
|
|
20591
20757
|
if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
20592
|
-
const tableId = (0,
|
|
20758
|
+
const tableId = (0, import_types90.infraId)("sql-table", signal.targetName);
|
|
20593
20759
|
if (graph.hasNode(tableId)) {
|
|
20594
|
-
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType:
|
|
20760
|
+
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types90.EdgeType.CALLS };
|
|
20595
20761
|
}
|
|
20596
|
-
const providerId = (0,
|
|
20762
|
+
const providerId = (0, import_types90.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
|
|
20597
20763
|
return {
|
|
20598
20764
|
targetNodeId: providerId,
|
|
20599
20765
|
serviceName: config.serviceName,
|
|
20600
|
-
edgeType:
|
|
20766
|
+
edgeType: import_types90.EdgeType.CALLS,
|
|
20601
20767
|
ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
|
|
20602
20768
|
};
|
|
20603
20769
|
};
|
|
@@ -20862,7 +21028,7 @@ function mapBuildsToSignals(builds, serviceName) {
|
|
|
20862
21028
|
|
|
20863
21029
|
// src/connectors/eas/resolve.ts
|
|
20864
21030
|
init_cjs_shims();
|
|
20865
|
-
var
|
|
21031
|
+
var import_types95 = require("@neat.is/types");
|
|
20866
21032
|
var NO_ENV2 = "unknown";
|
|
20867
21033
|
var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
|
|
20868
21034
|
var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
|
|
@@ -20878,8 +21044,8 @@ function configBasenamesForPhase(phase) {
|
|
|
20878
21044
|
function configNodeService(graph, configNodeId) {
|
|
20879
21045
|
for (const edgeId of graph.inboundEdges(configNodeId)) {
|
|
20880
21046
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
20881
|
-
if (edge.type !==
|
|
20882
|
-
const parsed = (0,
|
|
21047
|
+
if (edge.type !== import_types95.EdgeType.CONFIGURED_BY) continue;
|
|
21048
|
+
const parsed = (0, import_types95.parseFileId)(edge.source);
|
|
20883
21049
|
if (parsed) return parsed.service;
|
|
20884
21050
|
}
|
|
20885
21051
|
return null;
|
|
@@ -20890,7 +21056,7 @@ function findConfigNode(graph, basenames, serviceName) {
|
|
|
20890
21056
|
graph.forEachNode((id, attrs) => {
|
|
20891
21057
|
if (scoped) return;
|
|
20892
21058
|
const node = attrs;
|
|
20893
|
-
if (node.type !==
|
|
21059
|
+
if (node.type !== import_types95.NodeType.ConfigNode) return;
|
|
20894
21060
|
if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
|
|
20895
21061
|
if (anyMatch === null) anyMatch = id;
|
|
20896
21062
|
if (configNodeService(graph, id) === serviceName) scoped = id;
|
|
@@ -20907,13 +21073,13 @@ function createEasResolveTarget(graph) {
|
|
|
20907
21073
|
if (basenames.length > 0) {
|
|
20908
21074
|
const configNodeId = findConfigNode(graph, basenames, serviceName);
|
|
20909
21075
|
if (configNodeId) {
|
|
20910
|
-
return { targetNodeId: configNodeId, serviceName, edgeType:
|
|
21076
|
+
return { targetNodeId: configNodeId, serviceName, edgeType: import_types95.EdgeType.CALLS };
|
|
20911
21077
|
}
|
|
20912
21078
|
}
|
|
20913
21079
|
return {
|
|
20914
21080
|
targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV2),
|
|
20915
21081
|
serviceName,
|
|
20916
|
-
edgeType:
|
|
21082
|
+
edgeType: import_types95.EdgeType.CALLS
|
|
20917
21083
|
};
|
|
20918
21084
|
};
|
|
20919
21085
|
}
|
|
@@ -21628,11 +21794,11 @@ function registerRoutes(scope, ctx) {
|
|
|
21628
21794
|
const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
21629
21795
|
const parsed = [];
|
|
21630
21796
|
for (const c of candidates) {
|
|
21631
|
-
const r =
|
|
21797
|
+
const r = import_types98.DivergenceTypeSchema.safeParse(c);
|
|
21632
21798
|
if (!r.success) {
|
|
21633
21799
|
return reply.code(400).send({
|
|
21634
21800
|
error: `unknown divergence type "${c}"`,
|
|
21635
|
-
allowed:
|
|
21801
|
+
allowed: import_types98.DivergenceTypeSchema.options
|
|
21636
21802
|
});
|
|
21637
21803
|
}
|
|
21638
21804
|
parsed.push(r.data);
|
|
@@ -21749,6 +21915,7 @@ function registerRoutes(scope, ctx) {
|
|
|
21749
21915
|
reg.connector,
|
|
21750
21916
|
{
|
|
21751
21917
|
projectDir: proj.scanPath ?? "",
|
|
21918
|
+
project: proj.name,
|
|
21752
21919
|
credentials: reg.credentials,
|
|
21753
21920
|
...incidentsPath ? { errorsPath: incidentsPath } : {}
|
|
21754
21921
|
},
|
|
@@ -21812,6 +21979,39 @@ function registerRoutes(scope, ctx) {
|
|
|
21812
21979
|
if (!result) return reply.code(404).send({ error: "no root cause found", id: nodeId });
|
|
21813
21980
|
return result;
|
|
21814
21981
|
});
|
|
21982
|
+
scope.get("/graph/incident-card/:nodeId", async (req, reply) => {
|
|
21983
|
+
const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
|
|
21984
|
+
if (!proj) return;
|
|
21985
|
+
const { nodeId } = req.params;
|
|
21986
|
+
if (!proj.graph.hasNode(nodeId)) {
|
|
21987
|
+
return reply.code(404).send({ error: "node not found", id: nodeId });
|
|
21988
|
+
}
|
|
21989
|
+
const epath = errorsPathFor(proj);
|
|
21990
|
+
const incidents = epath ? await readErrorEvents(epath) : [];
|
|
21991
|
+
let errorEvent;
|
|
21992
|
+
if (req.query.errorId) {
|
|
21993
|
+
errorEvent = incidents.find((e) => e.id === req.query.errorId);
|
|
21994
|
+
if (!errorEvent) {
|
|
21995
|
+
return reply.code(404).send({ error: "error event not found", id: req.query.errorId });
|
|
21996
|
+
}
|
|
21997
|
+
} else {
|
|
21998
|
+
const svc = nodeId.replace(/^service:/, "");
|
|
21999
|
+
errorEvent = [...incidents].filter((e) => e.affectedNode === nodeId || e.service === svc).sort((a, b) => (b.timestamp ?? "").localeCompare(a.timestamp ?? ""))[0];
|
|
22000
|
+
if (!errorEvent) {
|
|
22001
|
+
return reply.code(404).send({ error: "no incident found for node", id: nodeId });
|
|
22002
|
+
}
|
|
22003
|
+
}
|
|
22004
|
+
const policyPath = ctx.policyFilePathFor(proj);
|
|
22005
|
+
let policies = [];
|
|
22006
|
+
if (policyPath) {
|
|
22007
|
+
try {
|
|
22008
|
+
policies = await loadPolicyFile(policyPath);
|
|
22009
|
+
} catch {
|
|
22010
|
+
policies = [];
|
|
22011
|
+
}
|
|
22012
|
+
}
|
|
22013
|
+
return buildIncidentCard(proj.graph, errorEvent, incidents, policies);
|
|
22014
|
+
});
|
|
21815
22015
|
scope.get("/graph/blast-radius/:nodeId", async (req, reply) => {
|
|
21816
22016
|
const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
|
|
21817
22017
|
if (!proj) return;
|
|
@@ -21994,7 +22194,7 @@ function registerRoutes(scope, ctx) {
|
|
|
21994
22194
|
const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
|
|
21995
22195
|
let violations = await log.readAll();
|
|
21996
22196
|
if (req.query.severity) {
|
|
21997
|
-
const sev =
|
|
22197
|
+
const sev = import_types98.PolicySeveritySchema.safeParse(req.query.severity);
|
|
21998
22198
|
if (!sev.success) {
|
|
21999
22199
|
return reply.code(400).send({
|
|
22000
22200
|
error: "invalid severity",
|
|
@@ -22033,7 +22233,7 @@ function registerRoutes(scope, ctx) {
|
|
|
22033
22233
|
scope.post("/policies/check", async (req, reply) => {
|
|
22034
22234
|
const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
|
|
22035
22235
|
if (!proj) return;
|
|
22036
|
-
const parsed =
|
|
22236
|
+
const parsed = import_types98.PoliciesCheckBodySchema.safeParse(req.body ?? {});
|
|
22037
22237
|
if (!parsed.success) {
|
|
22038
22238
|
return reply.code(400).send({
|
|
22039
22239
|
error: "invalid /policies/check body",
|