@neat.is/core 0.3.4 → 0.3.5
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-33ZZ2ZID.js → chunk-BUB3ASD5.js} +94 -83
- package/dist/chunk-BUB3ASD5.js.map +1 -0
- package/dist/{chunk-T3A2GK3X.js → chunk-KCEZSFU2.js} +2 -2
- package/dist/cli.cjs +94 -80
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/index.cjs +84 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +84 -70
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +57 -45
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-33ZZ2ZID.js.map +0 -1
- /package/dist/{chunk-T3A2GK3X.js.map → chunk-KCEZSFU2.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
routeSpanToProject,
|
|
3
3
|
startDaemon
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KCEZSFU2.js";
|
|
5
5
|
import {
|
|
6
6
|
ProjectNameCollisionError,
|
|
7
7
|
addProject,
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
thresholdForEdgeType,
|
|
38
38
|
touchLastSeen,
|
|
39
39
|
writeAtomically
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-BUB3ASD5.js";
|
|
41
41
|
import {
|
|
42
42
|
startOtelGrpcReceiver
|
|
43
43
|
} from "./chunk-G3PDTGOW.js";
|
package/dist/neatd.cjs
CHANGED
|
@@ -749,11 +749,16 @@ init_cjs_shims();
|
|
|
749
749
|
var import_types = require("@neat.is/types");
|
|
750
750
|
var ROOT_CAUSE_MAX_DEPTH = 5;
|
|
751
751
|
var BLAST_RADIUS_DEFAULT_DEPTH = 10;
|
|
752
|
+
function isFrontierNode(graph, nodeId) {
|
|
753
|
+
if (!graph.hasNode(nodeId)) return false;
|
|
754
|
+
const attrs = graph.getNodeAttributes(nodeId);
|
|
755
|
+
return attrs.type === import_types.NodeType.FrontierNode;
|
|
756
|
+
}
|
|
752
757
|
function bestEdgeBySource(graph, edgeIds) {
|
|
753
758
|
const best = /* @__PURE__ */ new Map();
|
|
754
759
|
for (const id of edgeIds) {
|
|
755
760
|
const e = graph.getEdgeAttributes(id);
|
|
756
|
-
if (e.
|
|
761
|
+
if (isFrontierNode(graph, e.source)) continue;
|
|
757
762
|
const cur = best.get(e.source);
|
|
758
763
|
if (!cur || import_types.PROV_RANK[e.provenance] > import_types.PROV_RANK[cur.provenance]) {
|
|
759
764
|
best.set(e.source, e);
|
|
@@ -765,7 +770,7 @@ function bestEdgeByTarget(graph, edgeIds) {
|
|
|
765
770
|
const best = /* @__PURE__ */ new Map();
|
|
766
771
|
for (const id of edgeIds) {
|
|
767
772
|
const e = graph.getEdgeAttributes(id);
|
|
768
|
-
if (e.
|
|
773
|
+
if (isFrontierNode(graph, e.target)) continue;
|
|
769
774
|
const cur = best.get(e.target);
|
|
770
775
|
if (!cur || import_types.PROV_RANK[e.provenance] > import_types.PROV_RANK[cur.provenance]) {
|
|
771
776
|
best.set(e.target, e);
|
|
@@ -777,8 +782,7 @@ var PROVENANCE_CEILING = {
|
|
|
777
782
|
OBSERVED: 1,
|
|
778
783
|
INFERRED: 0.7,
|
|
779
784
|
EXTRACTED: 0.5,
|
|
780
|
-
STALE: 0.3
|
|
781
|
-
FRONTIER: 0.3
|
|
785
|
+
STALE: 0.3
|
|
782
786
|
};
|
|
783
787
|
function volumeWeight(spanCount) {
|
|
784
788
|
if (!spanCount || spanCount <= 0) return 0.5;
|
|
@@ -1062,8 +1066,8 @@ var evaluateStructural = ({
|
|
|
1062
1066
|
for (const edgeId of graph.outboundEdges(id)) {
|
|
1063
1067
|
const e = graph.getEdgeAttributes(edgeId);
|
|
1064
1068
|
if (e.type !== rule.edgeType) continue;
|
|
1065
|
-
if (e.provenance === import_types2.Provenance.FRONTIER) continue;
|
|
1066
1069
|
const target = graph.getNodeAttributes(e.target);
|
|
1070
|
+
if (target.type === import_types2.NodeType.FrontierNode) continue;
|
|
1067
1071
|
if (target.type === rule.toNodeType) {
|
|
1068
1072
|
satisfied = true;
|
|
1069
1073
|
break;
|
|
@@ -1182,8 +1186,8 @@ var evaluateCompatibility = ({
|
|
|
1182
1186
|
for (const edgeId of graph.outboundEdges(svcId)) {
|
|
1183
1187
|
const e = graph.getEdgeAttributes(edgeId);
|
|
1184
1188
|
if (e.type !== import_types2.EdgeType.CONNECTS_TO) continue;
|
|
1185
|
-
if (e.provenance === import_types2.Provenance.FRONTIER) continue;
|
|
1186
1189
|
const dbAttrs = graph.getNodeAttributes(e.target);
|
|
1190
|
+
if (dbAttrs.type === import_types2.NodeType.FrontierNode) continue;
|
|
1187
1191
|
if (dbAttrs.type !== import_types2.NodeType.DatabaseNode) continue;
|
|
1188
1192
|
const db = dbAttrs;
|
|
1189
1193
|
for (const pair of compatPairs()) {
|
|
@@ -1478,31 +1482,6 @@ function ensureFrontierNode(graph, host, ts) {
|
|
|
1478
1482
|
graph.addNode(id, node);
|
|
1479
1483
|
return id;
|
|
1480
1484
|
}
|
|
1481
|
-
function upsertFrontierEdge(graph, type, source, target, ts) {
|
|
1482
|
-
const id = (0, import_types3.frontierEdgeId)(source, target, type);
|
|
1483
|
-
if (graph.hasEdge(id)) {
|
|
1484
|
-
const existing = graph.getEdgeAttributes(id);
|
|
1485
|
-
const updated = {
|
|
1486
|
-
...existing,
|
|
1487
|
-
provenance: import_types3.Provenance.FRONTIER,
|
|
1488
|
-
lastObserved: ts,
|
|
1489
|
-
callCount: (existing.callCount ?? 0) + 1
|
|
1490
|
-
};
|
|
1491
|
-
graph.replaceEdgeAttributes(id, updated);
|
|
1492
|
-
return;
|
|
1493
|
-
}
|
|
1494
|
-
const edge = {
|
|
1495
|
-
id,
|
|
1496
|
-
source,
|
|
1497
|
-
target,
|
|
1498
|
-
type,
|
|
1499
|
-
provenance: import_types3.Provenance.FRONTIER,
|
|
1500
|
-
confidence: 1,
|
|
1501
|
-
lastObserved: ts,
|
|
1502
|
-
callCount: 1
|
|
1503
|
-
};
|
|
1504
|
-
graph.addEdgeWithKey(id, source, target, edge);
|
|
1505
|
-
}
|
|
1506
1485
|
function upsertObservedEdge(graph, type, source, target, ts, isError = false) {
|
|
1507
1486
|
if (!graph.hasNode(source) || !graph.hasNode(target)) return null;
|
|
1508
1487
|
const id = makeObservedEdgeId(type, source, target);
|
|
@@ -1588,18 +1567,28 @@ async function appendErrorEvent(ctx, ev) {
|
|
|
1588
1567
|
await import_node_fs3.promises.mkdir(import_node_path3.default.dirname(ctx.errorsPath), { recursive: true });
|
|
1589
1568
|
await import_node_fs3.promises.appendFile(ctx.errorsPath, JSON.stringify(ev) + "\n", "utf8");
|
|
1590
1569
|
}
|
|
1570
|
+
function sanitizeAttributes(attrs) {
|
|
1571
|
+
const out = {};
|
|
1572
|
+
for (const [k, v] of Object.entries(attrs)) {
|
|
1573
|
+
if (typeof v === "bigint") out[k] = v.toString();
|
|
1574
|
+
else out[k] = v;
|
|
1575
|
+
}
|
|
1576
|
+
return out;
|
|
1577
|
+
}
|
|
1591
1578
|
function buildErrorEventForReceiver(span) {
|
|
1592
1579
|
if (span.statusCode !== 2) return null;
|
|
1593
1580
|
const ts = span.startTimeIso ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
1581
|
+
const attrs = sanitizeAttributes(span.attributes);
|
|
1594
1582
|
return {
|
|
1595
1583
|
id: `${span.traceId}:${span.spanId}`,
|
|
1596
1584
|
timestamp: ts,
|
|
1597
1585
|
service: span.service,
|
|
1598
1586
|
traceId: span.traceId,
|
|
1599
1587
|
spanId: span.spanId,
|
|
1600
|
-
errorMessage: span.exception?.message ?? span.
|
|
1588
|
+
errorMessage: span.exception?.message ?? span.name ?? "unknown error",
|
|
1601
1589
|
...span.exception?.type ? { exceptionType: span.exception.type } : {},
|
|
1602
1590
|
...span.exception?.stacktrace ? { exceptionStacktrace: span.exception.stacktrace } : {},
|
|
1591
|
+
...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
|
|
1603
1592
|
affectedNode: (0, import_types3.serviceId)(span.service)
|
|
1604
1593
|
};
|
|
1605
1594
|
}
|
|
@@ -1650,11 +1639,16 @@ async function handleSpan(ctx, span) {
|
|
|
1650
1639
|
affectedNode = targetId;
|
|
1651
1640
|
resolvedViaAddress = true;
|
|
1652
1641
|
} else if (!targetId) {
|
|
1653
|
-
const
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1642
|
+
const frontierNodeId = ensureFrontierNode(ctx.graph, host, ts);
|
|
1643
|
+
upsertObservedEdge(
|
|
1644
|
+
ctx.graph,
|
|
1645
|
+
import_types3.EdgeType.CALLS,
|
|
1646
|
+
sourceId,
|
|
1647
|
+
frontierNodeId,
|
|
1648
|
+
ts,
|
|
1649
|
+
isError
|
|
1650
|
+
);
|
|
1651
|
+
affectedNode = frontierNodeId;
|
|
1658
1652
|
resolvedViaAddress = true;
|
|
1659
1653
|
}
|
|
1660
1654
|
}
|
|
@@ -1676,15 +1670,17 @@ async function handleSpan(ctx, span) {
|
|
|
1676
1670
|
if (span.statusCode === 2) {
|
|
1677
1671
|
stitchTrace(ctx.graph, sourceId, ts);
|
|
1678
1672
|
if (ctx.writeErrorEventInline !== false) {
|
|
1673
|
+
const attrs = sanitizeAttributes(span.attributes);
|
|
1679
1674
|
const ev = {
|
|
1680
1675
|
id: `${span.traceId}:${span.spanId}`,
|
|
1681
1676
|
timestamp: ts,
|
|
1682
1677
|
service: span.service,
|
|
1683
1678
|
traceId: span.traceId,
|
|
1684
1679
|
spanId: span.spanId,
|
|
1685
|
-
errorMessage: span.exception?.message ?? span.
|
|
1680
|
+
errorMessage: span.exception?.message ?? span.name ?? "unknown error",
|
|
1686
1681
|
...span.exception?.type ? { exceptionType: span.exception.type } : {},
|
|
1687
1682
|
...span.exception?.stacktrace ? { exceptionStacktrace: span.exception.stacktrace } : {},
|
|
1683
|
+
...Object.keys(attrs).length > 0 ? { attributes: attrs } : {},
|
|
1688
1684
|
affectedNode
|
|
1689
1685
|
};
|
|
1690
1686
|
await appendErrorEvent(ctx, ev);
|
|
@@ -1740,8 +1736,7 @@ function rewireFrontierEdges(graph, frontierId2, serviceId3) {
|
|
|
1740
1736
|
}
|
|
1741
1737
|
function rebuildEdge(graph, edge, newSource, newTarget, oldEdgeId) {
|
|
1742
1738
|
graph.dropEdge(oldEdgeId);
|
|
1743
|
-
const
|
|
1744
|
-
const newId = promotedProvenance === import_types3.Provenance.OBSERVED ? (0, import_types3.observedEdgeId)(newSource, newTarget, edge.type) : promotedProvenance === import_types3.Provenance.INFERRED ? (0, import_types3.inferredEdgeId)(newSource, newTarget, edge.type) : promotedProvenance === import_types3.Provenance.EXTRACTED ? (0, import_types3.extractedEdgeId)(newSource, newTarget, edge.type) : (0, import_types3.frontierEdgeId)(newSource, newTarget, edge.type);
|
|
1739
|
+
const newId = edge.provenance === import_types3.Provenance.OBSERVED ? (0, import_types3.observedEdgeId)(newSource, newTarget, edge.type) : edge.provenance === import_types3.Provenance.INFERRED ? (0, import_types3.inferredEdgeId)(newSource, newTarget, edge.type) : (0, import_types3.extractedEdgeId)(newSource, newTarget, edge.type);
|
|
1745
1740
|
if (graph.hasEdge(newId)) {
|
|
1746
1741
|
const existing = graph.getEdgeAttributes(newId);
|
|
1747
1742
|
const merged = {
|
|
@@ -1756,8 +1751,7 @@ function rebuildEdge(graph, edge, newSource, newTarget, oldEdgeId) {
|
|
|
1756
1751
|
...edge,
|
|
1757
1752
|
id: newId,
|
|
1758
1753
|
source: newSource,
|
|
1759
|
-
target: newTarget
|
|
1760
|
-
provenance: promotedProvenance
|
|
1754
|
+
target: newTarget
|
|
1761
1755
|
};
|
|
1762
1756
|
graph.addEdgeWithKey(newId, newSource, newTarget, rebuilt);
|
|
1763
1757
|
}
|
|
@@ -3981,7 +3975,8 @@ async function extractFromDirectory(graph, scanPath, opts = {}) {
|
|
|
3981
3975
|
init_cjs_shims();
|
|
3982
3976
|
var import_node_fs18 = require("fs");
|
|
3983
3977
|
var import_node_path31 = __toESM(require("path"), 1);
|
|
3984
|
-
var
|
|
3978
|
+
var import_types19 = require("@neat.is/types");
|
|
3979
|
+
var SCHEMA_VERSION = 3;
|
|
3985
3980
|
function migrateV1ToV2(payload) {
|
|
3986
3981
|
const nodes = payload.graph.nodes;
|
|
3987
3982
|
if (Array.isArray(nodes)) {
|
|
@@ -3993,6 +3988,25 @@ function migrateV1ToV2(payload) {
|
|
|
3993
3988
|
}
|
|
3994
3989
|
return { ...payload, schemaVersion: 2 };
|
|
3995
3990
|
}
|
|
3991
|
+
function migrateV2ToV3(payload) {
|
|
3992
|
+
const edges = payload.graph.edges;
|
|
3993
|
+
if (Array.isArray(edges)) {
|
|
3994
|
+
for (const edge of edges) {
|
|
3995
|
+
const attrs = edge.attributes;
|
|
3996
|
+
if (!attrs || attrs.provenance !== "FRONTIER") continue;
|
|
3997
|
+
attrs.provenance = import_types19.Provenance.OBSERVED;
|
|
3998
|
+
const type = typeof attrs.type === "string" ? attrs.type : void 0;
|
|
3999
|
+
const source = typeof attrs.source === "string" ? attrs.source : void 0;
|
|
4000
|
+
const target = typeof attrs.target === "string" ? attrs.target : void 0;
|
|
4001
|
+
if (type && source && target) {
|
|
4002
|
+
const newId = (0, import_types19.observedEdgeId)(source, target, type);
|
|
4003
|
+
attrs.id = newId;
|
|
4004
|
+
if (edge.key) edge.key = newId;
|
|
4005
|
+
}
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
return { ...payload, schemaVersion: 3 };
|
|
4009
|
+
}
|
|
3996
4010
|
async function ensureDir(filePath) {
|
|
3997
4011
|
await import_node_fs18.promises.mkdir(import_node_path31.default.dirname(filePath), { recursive: true });
|
|
3998
4012
|
}
|
|
@@ -4019,6 +4033,9 @@ async function loadGraphFromDisk(graph, outPath) {
|
|
|
4019
4033
|
if (payload.schemaVersion === 1) {
|
|
4020
4034
|
payload = migrateV1ToV2(payload);
|
|
4021
4035
|
}
|
|
4036
|
+
if (payload.schemaVersion === 2) {
|
|
4037
|
+
payload = migrateV2ToV3(payload);
|
|
4038
|
+
}
|
|
4022
4039
|
if (payload.schemaVersion !== SCHEMA_VERSION) {
|
|
4023
4040
|
throw new Error(
|
|
4024
4041
|
`persist: unsupported snapshot schemaVersion ${payload.schemaVersion} (expected ${SCHEMA_VERSION})`
|
|
@@ -4117,11 +4134,11 @@ var Projects = class {
|
|
|
4117
4134
|
init_cjs_shims();
|
|
4118
4135
|
var import_fastify = __toESM(require("fastify"), 1);
|
|
4119
4136
|
var import_cors = __toESM(require("@fastify/cors"), 1);
|
|
4120
|
-
var
|
|
4137
|
+
var import_types22 = require("@neat.is/types");
|
|
4121
4138
|
|
|
4122
4139
|
// src/divergences.ts
|
|
4123
4140
|
init_cjs_shims();
|
|
4124
|
-
var
|
|
4141
|
+
var import_types20 = require("@neat.is/types");
|
|
4125
4142
|
function bucketKey(source, target, type) {
|
|
4126
4143
|
return `${type}|${source}|${target}`;
|
|
4127
4144
|
}
|
|
@@ -4129,25 +4146,22 @@ function bucketEdges(graph) {
|
|
|
4129
4146
|
const buckets = /* @__PURE__ */ new Map();
|
|
4130
4147
|
graph.forEachEdge((id, attrs) => {
|
|
4131
4148
|
const e = attrs;
|
|
4132
|
-
const parsed = (0,
|
|
4149
|
+
const parsed = (0, import_types20.parseEdgeId)(id);
|
|
4133
4150
|
const provenance = parsed?.provenance ?? e.provenance;
|
|
4134
4151
|
const key = bucketKey(e.source, e.target, e.type);
|
|
4135
4152
|
const cur = buckets.get(key) ?? { source: e.source, target: e.target, type: e.type };
|
|
4136
4153
|
switch (provenance) {
|
|
4137
|
-
case
|
|
4154
|
+
case import_types20.Provenance.EXTRACTED:
|
|
4138
4155
|
cur.extracted = e;
|
|
4139
4156
|
break;
|
|
4140
|
-
case
|
|
4157
|
+
case import_types20.Provenance.OBSERVED:
|
|
4141
4158
|
cur.observed = e;
|
|
4142
4159
|
break;
|
|
4143
|
-
case
|
|
4160
|
+
case import_types20.Provenance.INFERRED:
|
|
4144
4161
|
cur.inferred = e;
|
|
4145
4162
|
break;
|
|
4146
|
-
case import_types19.Provenance.FRONTIER:
|
|
4147
|
-
cur.frontier = e;
|
|
4148
|
-
break;
|
|
4149
4163
|
default:
|
|
4150
|
-
if (e.provenance ===
|
|
4164
|
+
if (e.provenance === import_types20.Provenance.STALE) cur.stale = e;
|
|
4151
4165
|
}
|
|
4152
4166
|
buckets.set(key, cur);
|
|
4153
4167
|
});
|
|
@@ -4156,7 +4170,7 @@ function bucketEdges(graph) {
|
|
|
4156
4170
|
function nodeIsFrontier(graph, nodeId) {
|
|
4157
4171
|
if (!graph.hasNode(nodeId)) return false;
|
|
4158
4172
|
const attrs = graph.getNodeAttributes(nodeId);
|
|
4159
|
-
return attrs.type ===
|
|
4173
|
+
return attrs.type === import_types20.NodeType.FrontierNode;
|
|
4160
4174
|
}
|
|
4161
4175
|
function clampConfidence(n) {
|
|
4162
4176
|
if (!Number.isFinite(n)) return 0;
|
|
@@ -4217,7 +4231,7 @@ function declaredHostFor(svc) {
|
|
|
4217
4231
|
function hasExtractedConfiguredBy(graph, svcId) {
|
|
4218
4232
|
for (const edgeId of graph.outboundEdges(svcId)) {
|
|
4219
4233
|
const e = graph.getEdgeAttributes(edgeId);
|
|
4220
|
-
if (e.type ===
|
|
4234
|
+
if (e.type === import_types20.EdgeType.CONFIGURED_BY && e.provenance === import_types20.Provenance.EXTRACTED) {
|
|
4221
4235
|
return true;
|
|
4222
4236
|
}
|
|
4223
4237
|
}
|
|
@@ -4230,10 +4244,10 @@ function detectHostMismatch(graph, svcId, svc) {
|
|
|
4230
4244
|
const out = [];
|
|
4231
4245
|
for (const edgeId of graph.outboundEdges(svcId)) {
|
|
4232
4246
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
4233
|
-
if (edge.type !==
|
|
4234
|
-
if (edge.provenance !==
|
|
4247
|
+
if (edge.type !== import_types20.EdgeType.CONNECTS_TO) continue;
|
|
4248
|
+
if (edge.provenance !== import_types20.Provenance.OBSERVED) continue;
|
|
4235
4249
|
const target = graph.getNodeAttributes(edge.target);
|
|
4236
|
-
if (target.type !==
|
|
4250
|
+
if (target.type !== import_types20.NodeType.DatabaseNode) continue;
|
|
4237
4251
|
const observedHost = target.host?.trim();
|
|
4238
4252
|
if (!observedHost) continue;
|
|
4239
4253
|
if (observedHost === declaredHost) continue;
|
|
@@ -4255,10 +4269,10 @@ function detectCompatDivergences(graph, svcId, svc) {
|
|
|
4255
4269
|
const deps = svc.dependencies ?? {};
|
|
4256
4270
|
for (const edgeId of graph.outboundEdges(svcId)) {
|
|
4257
4271
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
4258
|
-
if (edge.type !==
|
|
4259
|
-
if (edge.provenance !==
|
|
4272
|
+
if (edge.type !== import_types20.EdgeType.CONNECTS_TO) continue;
|
|
4273
|
+
if (edge.provenance !== import_types20.Provenance.OBSERVED) continue;
|
|
4260
4274
|
const target = graph.getNodeAttributes(edge.target);
|
|
4261
|
-
if (target.type !==
|
|
4275
|
+
if (target.type !== import_types20.NodeType.DatabaseNode) continue;
|
|
4262
4276
|
for (const pair of compatPairs()) {
|
|
4263
4277
|
if (pair.engine !== target.engine) continue;
|
|
4264
4278
|
const declared = deps[pair.driver];
|
|
@@ -4319,7 +4333,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
4319
4333
|
}
|
|
4320
4334
|
graph.forEachNode((nodeId, attrs) => {
|
|
4321
4335
|
const n = attrs;
|
|
4322
|
-
if (n.type !==
|
|
4336
|
+
if (n.type !== import_types20.NodeType.ServiceNode) return;
|
|
4323
4337
|
const svc = n;
|
|
4324
4338
|
for (const d of detectHostMismatch(graph, nodeId, svc)) all.push(d);
|
|
4325
4339
|
for (const d of detectCompatDivergences(graph, nodeId, svc)) all.push(d);
|
|
@@ -4352,7 +4366,7 @@ function computeDivergences(graph, opts = {}) {
|
|
|
4352
4366
|
if (a.source !== b.source) return a.source.localeCompare(b.source);
|
|
4353
4367
|
return a.target.localeCompare(b.target);
|
|
4354
4368
|
});
|
|
4355
|
-
return
|
|
4369
|
+
return import_types20.DivergenceResultSchema.parse({
|
|
4356
4370
|
divergences: filtered,
|
|
4357
4371
|
totalAffected: filtered.length,
|
|
4358
4372
|
computedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -4441,7 +4455,7 @@ init_cjs_shims();
|
|
|
4441
4455
|
var import_node_fs20 = require("fs");
|
|
4442
4456
|
var import_node_os2 = __toESM(require("os"), 1);
|
|
4443
4457
|
var import_node_path33 = __toESM(require("path"), 1);
|
|
4444
|
-
var
|
|
4458
|
+
var import_types21 = require("@neat.is/types");
|
|
4445
4459
|
var LOCK_TIMEOUT_MS = 5e3;
|
|
4446
4460
|
var LOCK_RETRY_MS = 50;
|
|
4447
4461
|
function neatHome() {
|
|
@@ -4512,10 +4526,10 @@ async function readRegistry() {
|
|
|
4512
4526
|
throw err;
|
|
4513
4527
|
}
|
|
4514
4528
|
const parsed = JSON.parse(raw);
|
|
4515
|
-
return
|
|
4529
|
+
return import_types21.RegistryFileSchema.parse(parsed);
|
|
4516
4530
|
}
|
|
4517
4531
|
async function writeRegistry(reg) {
|
|
4518
|
-
const validated =
|
|
4532
|
+
const validated = import_types21.RegistryFileSchema.parse(reg);
|
|
4519
4533
|
await writeAtomically(registryPath(), JSON.stringify(validated, null, 2) + "\n");
|
|
4520
4534
|
}
|
|
4521
4535
|
async function getProject(name) {
|
|
@@ -4725,11 +4739,11 @@ function registerRoutes(scope, ctx) {
|
|
|
4725
4739
|
const candidates = req2.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
4726
4740
|
const parsed = [];
|
|
4727
4741
|
for (const c of candidates) {
|
|
4728
|
-
const r =
|
|
4742
|
+
const r = import_types22.DivergenceTypeSchema.safeParse(c);
|
|
4729
4743
|
if (!r.success) {
|
|
4730
4744
|
return reply.code(400).send({
|
|
4731
4745
|
error: `unknown divergence type "${c}"`,
|
|
4732
|
-
allowed:
|
|
4746
|
+
allowed: import_types22.DivergenceTypeSchema.options
|
|
4733
4747
|
});
|
|
4734
4748
|
}
|
|
4735
4749
|
parsed.push(r.data);
|
|
@@ -4913,7 +4927,7 @@ function registerRoutes(scope, ctx) {
|
|
|
4913
4927
|
const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
|
|
4914
4928
|
let violations = await log.readAll();
|
|
4915
4929
|
if (req2.query.severity) {
|
|
4916
|
-
const sev =
|
|
4930
|
+
const sev = import_types22.PolicySeveritySchema.safeParse(req2.query.severity);
|
|
4917
4931
|
if (!sev.success) {
|
|
4918
4932
|
return reply.code(400).send({
|
|
4919
4933
|
error: "invalid severity",
|
|
@@ -4930,7 +4944,7 @@ function registerRoutes(scope, ctx) {
|
|
|
4930
4944
|
scope.post("/policies/check", async (req2, reply) => {
|
|
4931
4945
|
const proj = resolveProject(registry, req2, reply);
|
|
4932
4946
|
if (!proj) return;
|
|
4933
|
-
const parsed =
|
|
4947
|
+
const parsed = import_types22.PoliciesCheckBodySchema.safeParse(req2.body ?? {});
|
|
4934
4948
|
if (!parsed.success) {
|
|
4935
4949
|
return reply.code(400).send({
|
|
4936
4950
|
error: "invalid /policies/check body",
|