@neat.is/core 0.9.5-dev.20260824 → 0.9.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-TGCWMMF6.js → chunk-4SLKQNG7.js} +2 -2
- package/dist/{chunk-IVVF37OU.js → chunk-DGAI4VOE.js} +264 -19
- package/dist/chunk-DGAI4VOE.js.map +1 -0
- package/dist/cli.cjs +1873 -1466
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1534 -1382
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +280 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +280 -26
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +278 -24
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-IVVF37OU.js.map +0 -1
- /package/dist/{chunk-TGCWMMF6.js.map → chunk-4SLKQNG7.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-4SLKQNG7.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-DGAI4VOE.js";
|
|
41
41
|
import {
|
|
42
42
|
startOtelGrpcReceiver
|
|
43
43
|
} from "./chunk-ERE47MCR.js";
|
package/dist/neatd.cjs
CHANGED
|
@@ -16021,7 +16021,7 @@ var Projects = class {
|
|
|
16021
16021
|
init_cjs_shims();
|
|
16022
16022
|
var import_fastify2 = __toESM(require("fastify"), 1);
|
|
16023
16023
|
var import_cors = __toESM(require("@fastify/cors"), 1);
|
|
16024
|
-
var
|
|
16024
|
+
var import_types97 = require("@neat.is/types");
|
|
16025
16025
|
|
|
16026
16026
|
// src/extend/index.ts
|
|
16027
16027
|
init_cjs_shims();
|
|
@@ -20130,9 +20130,229 @@ function createCloudRunConnector(graph, config = {}) {
|
|
|
20130
20130
|
};
|
|
20131
20131
|
}
|
|
20132
20132
|
|
|
20133
|
+
// src/connectors/gcp-lb/index.ts
|
|
20134
|
+
init_cjs_shims();
|
|
20135
|
+
|
|
20136
|
+
// src/connectors/gcp-lb/client.ts
|
|
20137
|
+
init_cjs_shims();
|
|
20138
|
+
function gcpLbRequestLogName(projectId) {
|
|
20139
|
+
return `projects/${projectId}/logs/requests`;
|
|
20140
|
+
}
|
|
20141
|
+
function buildGcpLbEntriesFilter(projectId, sinceIso) {
|
|
20142
|
+
return [
|
|
20143
|
+
`logName = "${gcpLbRequestLogName(projectId)}"`,
|
|
20144
|
+
`resource.type = "${GCP_LB_RESOURCE_TYPE}"`,
|
|
20145
|
+
'httpRequest.requestMethod != ""',
|
|
20146
|
+
`timestamp >= "${sinceIso}"`
|
|
20147
|
+
].join(" AND ");
|
|
20148
|
+
}
|
|
20149
|
+
var GCP_LB_RESOURCE_TYPE = "http_load_balancer";
|
|
20150
|
+
var DEFAULT_LOOKBACK_MS3 = 24 * 60 * 60 * 1e3;
|
|
20151
|
+
var ENTRIES_LIST_URL3 = "https://logging.googleapis.com/v2/entries:list";
|
|
20152
|
+
var PAGE_SIZE3 = 1e3;
|
|
20153
|
+
var MAX_PAGES3 = 20;
|
|
20154
|
+
async function fetchGcpLbRequestLogEntries(creds, sinceIso, apiUrl = ENTRIES_LIST_URL3) {
|
|
20155
|
+
const filter = buildGcpLbEntriesFilter(creds.projectId, sinceIso);
|
|
20156
|
+
const out = [];
|
|
20157
|
+
let pageToken;
|
|
20158
|
+
for (let page = 0; page < MAX_PAGES3; page++) {
|
|
20159
|
+
const body = {
|
|
20160
|
+
resourceNames: [`projects/${creds.projectId}`],
|
|
20161
|
+
filter,
|
|
20162
|
+
orderBy: "timestamp asc",
|
|
20163
|
+
pageSize: PAGE_SIZE3,
|
|
20164
|
+
...pageToken ? { pageToken } : {}
|
|
20165
|
+
};
|
|
20166
|
+
const res = await junctionFetch(
|
|
20167
|
+
apiUrl,
|
|
20168
|
+
{
|
|
20169
|
+
method: "POST",
|
|
20170
|
+
headers: {
|
|
20171
|
+
...bearerAuthHeader(creds.accessToken),
|
|
20172
|
+
"Content-Type": "application/json"
|
|
20173
|
+
},
|
|
20174
|
+
body: JSON.stringify(body)
|
|
20175
|
+
},
|
|
20176
|
+
// accountKey: the GCP project id — one customer's Cloud Logging quota is
|
|
20177
|
+
// scoped per GCP project (ADR-131's per-(provider, accountKey) rate-limit
|
|
20178
|
+
// bucket), the same key Cloud Run's and Firebase's connectors use.
|
|
20179
|
+
{ provider: "gcp-lb", accountKey: creds.projectId }
|
|
20180
|
+
);
|
|
20181
|
+
if (!res.ok) {
|
|
20182
|
+
throw new Error(`Cloud Logging entries.list failed: ${res.status} ${res.statusText}`);
|
|
20183
|
+
}
|
|
20184
|
+
const json = await res.json();
|
|
20185
|
+
if (Array.isArray(json.entries)) out.push(...json.entries);
|
|
20186
|
+
if (!json.nextPageToken) break;
|
|
20187
|
+
pageToken = json.nextPageToken;
|
|
20188
|
+
}
|
|
20189
|
+
return out;
|
|
20190
|
+
}
|
|
20191
|
+
|
|
20192
|
+
// src/connectors/gcp-lb/map.ts
|
|
20193
|
+
init_cjs_shims();
|
|
20194
|
+
|
|
20195
|
+
// src/connectors/gcp-lb/types.ts
|
|
20196
|
+
init_cjs_shims();
|
|
20197
|
+
function readGcpLbCredentials(raw) {
|
|
20198
|
+
const projectId = raw["projectId"];
|
|
20199
|
+
const accessToken = raw["accessToken"];
|
|
20200
|
+
if (typeof projectId !== "string" || projectId.length === 0) {
|
|
20201
|
+
throw new Error("gcp-lb connector: credentials.projectId must be a non-empty string");
|
|
20202
|
+
}
|
|
20203
|
+
if (typeof accessToken !== "string" || accessToken.length === 0) {
|
|
20204
|
+
throw new Error("gcp-lb connector: credentials.accessToken must be a non-empty string");
|
|
20205
|
+
}
|
|
20206
|
+
return { projectId, accessToken };
|
|
20207
|
+
}
|
|
20208
|
+
var GCP_LB_TARGET_KIND = "http_load_balancer";
|
|
20209
|
+
var FIELD_SEP3 = "\0";
|
|
20210
|
+
function packGcpLbTargetName(identity) {
|
|
20211
|
+
return [identity.backendServiceName, identity.method, identity.path].join(FIELD_SEP3);
|
|
20212
|
+
}
|
|
20213
|
+
function parseGcpLbTargetName(targetName) {
|
|
20214
|
+
const firstSep = targetName.indexOf(FIELD_SEP3);
|
|
20215
|
+
if (firstSep === -1) return null;
|
|
20216
|
+
const backendServiceName = targetName.slice(0, firstSep);
|
|
20217
|
+
const rest = targetName.slice(firstSep + 1);
|
|
20218
|
+
const secondSep = rest.indexOf(FIELD_SEP3);
|
|
20219
|
+
if (secondSep === -1) return null;
|
|
20220
|
+
const method = rest.slice(0, secondSep);
|
|
20221
|
+
const path78 = rest.slice(secondSep + 1);
|
|
20222
|
+
if (!backendServiceName || !method || !path78) return null;
|
|
20223
|
+
return { backendServiceName, method, path: path78 };
|
|
20224
|
+
}
|
|
20225
|
+
|
|
20226
|
+
// src/connectors/gcp-lb/map.ts
|
|
20227
|
+
var GCP_LB_RESOURCE_TYPE2 = "http_load_balancer";
|
|
20228
|
+
function pathFromRequestUrl3(requestUrl) {
|
|
20229
|
+
if (typeof requestUrl !== "string" || requestUrl.length === 0) return null;
|
|
20230
|
+
if (requestUrl.startsWith("/")) {
|
|
20231
|
+
const withoutQuery = requestUrl.split("?")[0];
|
|
20232
|
+
return withoutQuery && withoutQuery.length > 0 ? withoutQuery : "/";
|
|
20233
|
+
}
|
|
20234
|
+
try {
|
|
20235
|
+
const candidate = requestUrl.startsWith("//") ? `https:${requestUrl}` : requestUrl;
|
|
20236
|
+
const parsed = new URL(candidate);
|
|
20237
|
+
return parsed.pathname || "/";
|
|
20238
|
+
} catch {
|
|
20239
|
+
return null;
|
|
20240
|
+
}
|
|
20241
|
+
}
|
|
20242
|
+
var ERROR_STATUS_THRESHOLD5 = 500;
|
|
20243
|
+
function mapLogEntryToSignal3(entry2) {
|
|
20244
|
+
if (!entry2 || typeof entry2 !== "object") return null;
|
|
20245
|
+
if (entry2.resource?.type !== GCP_LB_RESOURCE_TYPE2) return null;
|
|
20246
|
+
const backendServiceName = entry2.resource?.labels?.["backend_service_name"];
|
|
20247
|
+
if (typeof backendServiceName !== "string" || backendServiceName.length === 0) return null;
|
|
20248
|
+
const req2 = entry2.httpRequest;
|
|
20249
|
+
if (!req2) return null;
|
|
20250
|
+
if (typeof req2.requestMethod !== "string" || req2.requestMethod.length === 0) return null;
|
|
20251
|
+
const method = req2.requestMethod.toUpperCase();
|
|
20252
|
+
const path78 = pathFromRequestUrl3(req2.requestUrl);
|
|
20253
|
+
if (path78 === null) return null;
|
|
20254
|
+
const timestamp = entry2.timestamp;
|
|
20255
|
+
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
20256
|
+
const isError = typeof req2.status === "number" && req2.status >= ERROR_STATUS_THRESHOLD5;
|
|
20257
|
+
return {
|
|
20258
|
+
targetKind: GCP_LB_TARGET_KIND,
|
|
20259
|
+
targetName: packGcpLbTargetName({ backendServiceName, method, path: path78 }),
|
|
20260
|
+
callCount: 1,
|
|
20261
|
+
errorCount: isError ? 1 : 0,
|
|
20262
|
+
lastObservedIso: timestamp
|
|
20263
|
+
};
|
|
20264
|
+
}
|
|
20265
|
+
function mapLogEntriesToSignals3(entries) {
|
|
20266
|
+
const out = [];
|
|
20267
|
+
for (const entry2 of entries) {
|
|
20268
|
+
const signal = mapLogEntryToSignal3(entry2);
|
|
20269
|
+
if (signal) out.push(signal);
|
|
20270
|
+
}
|
|
20271
|
+
return out;
|
|
20272
|
+
}
|
|
20273
|
+
|
|
20274
|
+
// src/connectors/gcp-lb/resolve.ts
|
|
20275
|
+
init_cjs_shims();
|
|
20276
|
+
var import_types82 = require("@neat.is/types");
|
|
20277
|
+
var GCP_LB_BACKEND_INFRA_KIND = "gcp-lb-backend";
|
|
20278
|
+
function findMatchingRouteNode3(graph, serviceName, method, normalizedPath) {
|
|
20279
|
+
let found = null;
|
|
20280
|
+
graph.forEachNode((_id, attrs) => {
|
|
20281
|
+
if (found) return;
|
|
20282
|
+
const node = attrs;
|
|
20283
|
+
if (node.type !== import_types82.NodeType.RouteNode) return;
|
|
20284
|
+
const route = attrs;
|
|
20285
|
+
if (route.service !== serviceName || !route.pathTemplate) return;
|
|
20286
|
+
if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
|
|
20287
|
+
const routeMethod = route.method.toUpperCase();
|
|
20288
|
+
if (routeMethod !== "ALL" && routeMethod !== method) return;
|
|
20289
|
+
found = route.id;
|
|
20290
|
+
});
|
|
20291
|
+
return found;
|
|
20292
|
+
}
|
|
20293
|
+
function createGcpLbResolveTarget(graph, config) {
|
|
20294
|
+
return (signal) => {
|
|
20295
|
+
if (signal.targetKind !== GCP_LB_TARGET_KIND) return null;
|
|
20296
|
+
const identity = parseGcpLbTargetName(signal.targetName);
|
|
20297
|
+
if (!identity) return null;
|
|
20298
|
+
const { backendServiceName, method, path: path78 } = identity;
|
|
20299
|
+
const mappedService = config.backendServiceMap?.[backendServiceName];
|
|
20300
|
+
if (mappedService) {
|
|
20301
|
+
const routeNodeId = findMatchingRouteNode3(
|
|
20302
|
+
graph,
|
|
20303
|
+
mappedService,
|
|
20304
|
+
method,
|
|
20305
|
+
normalizePathTemplate(path78)
|
|
20306
|
+
);
|
|
20307
|
+
if (routeNodeId) {
|
|
20308
|
+
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types82.EdgeType.CALLS };
|
|
20309
|
+
}
|
|
20310
|
+
}
|
|
20311
|
+
return {
|
|
20312
|
+
targetNodeId: (0, import_types82.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
|
|
20313
|
+
serviceName: mappedService ?? backendServiceName,
|
|
20314
|
+
edgeType: import_types82.EdgeType.CALLS,
|
|
20315
|
+
ensureInfraNode: {
|
|
20316
|
+
kind: GCP_LB_BACKEND_INFRA_KIND,
|
|
20317
|
+
name: backendServiceName,
|
|
20318
|
+
provider: "gcp-lb"
|
|
20319
|
+
}
|
|
20320
|
+
};
|
|
20321
|
+
};
|
|
20322
|
+
}
|
|
20323
|
+
|
|
20324
|
+
// src/connectors/gcp-lb/index.ts
|
|
20325
|
+
var GcpLbConnector = class {
|
|
20326
|
+
constructor(config = {}) {
|
|
20327
|
+
this.config = config;
|
|
20328
|
+
}
|
|
20329
|
+
config;
|
|
20330
|
+
provider = "gcp-lb";
|
|
20331
|
+
async poll(ctx) {
|
|
20332
|
+
const creds = readGcpLbCredentials(ctx.credentials);
|
|
20333
|
+
const maxLookbackMs = this.config.maxLookbackMs ?? DEFAULT_LOOKBACK_MS3;
|
|
20334
|
+
const sinceIso = boundedSinceIso2(ctx.since, /* @__PURE__ */ new Date(), maxLookbackMs);
|
|
20335
|
+
const entries = await fetchGcpLbRequestLogEntries(creds, sinceIso, this.config.apiUrl);
|
|
20336
|
+
return mapLogEntriesToSignals3(entries);
|
|
20337
|
+
}
|
|
20338
|
+
};
|
|
20339
|
+
function boundedSinceIso2(since, now, maxLookbackMs) {
|
|
20340
|
+
const floor = new Date(now.getTime() - maxLookbackMs);
|
|
20341
|
+
if (!since) return floor.toISOString();
|
|
20342
|
+
const sinceMs = new Date(since).getTime();
|
|
20343
|
+
if (Number.isNaN(sinceMs)) return floor.toISOString();
|
|
20344
|
+
return sinceMs < floor.getTime() ? floor.toISOString() : new Date(sinceMs).toISOString();
|
|
20345
|
+
}
|
|
20346
|
+
function createGcpLbConnector(graph, config = {}) {
|
|
20347
|
+
return {
|
|
20348
|
+
connector: new GcpLbConnector(config),
|
|
20349
|
+
resolveTarget: createGcpLbResolveTarget(graph, config)
|
|
20350
|
+
};
|
|
20351
|
+
}
|
|
20352
|
+
|
|
20133
20353
|
// src/connectors/render/index.ts
|
|
20134
20354
|
init_cjs_shims();
|
|
20135
|
-
var
|
|
20355
|
+
var import_types85 = require("@neat.is/types");
|
|
20136
20356
|
|
|
20137
20357
|
// src/connectors/render/types.ts
|
|
20138
20358
|
init_cjs_shims();
|
|
@@ -20210,7 +20430,7 @@ function buildRenderRouteIndex(graph, serviceName) {
|
|
|
20210
20430
|
const out = [];
|
|
20211
20431
|
graph.forEachNode((_id, attrs) => {
|
|
20212
20432
|
const node = attrs;
|
|
20213
|
-
if (node.type !==
|
|
20433
|
+
if (node.type !== import_types85.NodeType.RouteNode) return;
|
|
20214
20434
|
const route = attrs;
|
|
20215
20435
|
if (route.service !== serviceName) return;
|
|
20216
20436
|
out.push({
|
|
@@ -20295,7 +20515,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
|
|
|
20295
20515
|
function createRenderResolveTarget(config) {
|
|
20296
20516
|
return (signal) => {
|
|
20297
20517
|
if (signal.targetKind === ROUTE_TARGET_KIND2) {
|
|
20298
|
-
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType:
|
|
20518
|
+
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types85.EdgeType.CALLS };
|
|
20299
20519
|
}
|
|
20300
20520
|
return null;
|
|
20301
20521
|
};
|
|
@@ -20433,21 +20653,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
|
|
|
20433
20653
|
|
|
20434
20654
|
// src/connectors/planetscale/resolve.ts
|
|
20435
20655
|
init_cjs_shims();
|
|
20436
|
-
var
|
|
20656
|
+
var import_types89 = require("@neat.is/types");
|
|
20437
20657
|
var PLANETSCALE_DATABASE_KIND = "planetscale-database";
|
|
20438
20658
|
function createPlanetscaleResolveTarget(graph, config) {
|
|
20439
20659
|
const databaseName = `${config.organization}/${config.database}`;
|
|
20440
20660
|
return (signal, _ctx) => {
|
|
20441
20661
|
if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
20442
|
-
const tableId = (0,
|
|
20662
|
+
const tableId = (0, import_types89.infraId)("sql-table", signal.targetName);
|
|
20443
20663
|
if (graph.hasNode(tableId)) {
|
|
20444
|
-
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType:
|
|
20664
|
+
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types89.EdgeType.CALLS };
|
|
20445
20665
|
}
|
|
20446
|
-
const providerId = (0,
|
|
20666
|
+
const providerId = (0, import_types89.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
|
|
20447
20667
|
return {
|
|
20448
20668
|
targetNodeId: providerId,
|
|
20449
20669
|
serviceName: config.serviceName,
|
|
20450
|
-
edgeType:
|
|
20670
|
+
edgeType: import_types89.EdgeType.CALLS,
|
|
20451
20671
|
ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
|
|
20452
20672
|
};
|
|
20453
20673
|
};
|
|
@@ -20513,13 +20733,13 @@ function isTransientFailure(err) {
|
|
|
20513
20733
|
if (code && INTERNAL_ERROR_CODE.test(code)) return true;
|
|
20514
20734
|
return false;
|
|
20515
20735
|
}
|
|
20516
|
-
var
|
|
20736
|
+
var FIELD_SEP4 = "\0";
|
|
20517
20737
|
var EAS_TARGET_KIND = "eas-build";
|
|
20518
20738
|
function packEasTargetName(identity) {
|
|
20519
|
-
return [identity.serviceName, identity.phase].join(
|
|
20739
|
+
return [identity.serviceName, identity.phase].join(FIELD_SEP4);
|
|
20520
20740
|
}
|
|
20521
20741
|
function parseEasTargetName(targetName) {
|
|
20522
|
-
const sep = targetName.indexOf(
|
|
20742
|
+
const sep = targetName.indexOf(FIELD_SEP4);
|
|
20523
20743
|
if (sep === -1) return null;
|
|
20524
20744
|
const serviceName = targetName.slice(0, sep);
|
|
20525
20745
|
const phase = targetName.slice(sep + 1);
|
|
@@ -20712,7 +20932,7 @@ function mapBuildsToSignals(builds, serviceName) {
|
|
|
20712
20932
|
|
|
20713
20933
|
// src/connectors/eas/resolve.ts
|
|
20714
20934
|
init_cjs_shims();
|
|
20715
|
-
var
|
|
20935
|
+
var import_types94 = require("@neat.is/types");
|
|
20716
20936
|
var NO_ENV2 = "unknown";
|
|
20717
20937
|
var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
|
|
20718
20938
|
var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
|
|
@@ -20728,8 +20948,8 @@ function configBasenamesForPhase(phase) {
|
|
|
20728
20948
|
function configNodeService(graph, configNodeId) {
|
|
20729
20949
|
for (const edgeId of graph.inboundEdges(configNodeId)) {
|
|
20730
20950
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
20731
|
-
if (edge.type !==
|
|
20732
|
-
const parsed = (0,
|
|
20951
|
+
if (edge.type !== import_types94.EdgeType.CONFIGURED_BY) continue;
|
|
20952
|
+
const parsed = (0, import_types94.parseFileId)(edge.source);
|
|
20733
20953
|
if (parsed) return parsed.service;
|
|
20734
20954
|
}
|
|
20735
20955
|
return null;
|
|
@@ -20740,7 +20960,7 @@ function findConfigNode(graph, basenames, serviceName) {
|
|
|
20740
20960
|
graph.forEachNode((id, attrs) => {
|
|
20741
20961
|
if (scoped) return;
|
|
20742
20962
|
const node = attrs;
|
|
20743
|
-
if (node.type !==
|
|
20963
|
+
if (node.type !== import_types94.NodeType.ConfigNode) return;
|
|
20744
20964
|
if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
|
|
20745
20965
|
if (anyMatch === null) anyMatch = id;
|
|
20746
20966
|
if (configNodeService(graph, id) === serviceName) scoped = id;
|
|
@@ -20757,13 +20977,13 @@ function createEasResolveTarget(graph) {
|
|
|
20757
20977
|
if (basenames.length > 0) {
|
|
20758
20978
|
const configNodeId = findConfigNode(graph, basenames, serviceName);
|
|
20759
20979
|
if (configNodeId) {
|
|
20760
|
-
return { targetNodeId: configNodeId, serviceName, edgeType:
|
|
20980
|
+
return { targetNodeId: configNodeId, serviceName, edgeType: import_types94.EdgeType.CALLS };
|
|
20761
20981
|
}
|
|
20762
20982
|
}
|
|
20763
20983
|
return {
|
|
20764
20984
|
targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV2),
|
|
20765
20985
|
serviceName,
|
|
20766
|
-
edgeType:
|
|
20986
|
+
edgeType: import_types94.EdgeType.CALLS
|
|
20767
20987
|
};
|
|
20768
20988
|
};
|
|
20769
20989
|
}
|
|
@@ -20775,7 +20995,7 @@ function isBuildSince(build, sinceIso) {
|
|
|
20775
20995
|
if (Number.isNaN(t) || Number.isNaN(s)) return true;
|
|
20776
20996
|
return t > s;
|
|
20777
20997
|
}
|
|
20778
|
-
function
|
|
20998
|
+
function boundedSinceIso3(since, now, maxLookbackMs) {
|
|
20779
20999
|
const floor = new Date(now.getTime() - maxLookbackMs);
|
|
20780
21000
|
if (!since) return floor.toISOString();
|
|
20781
21001
|
const sinceMs = new Date(since).getTime();
|
|
@@ -20794,7 +21014,7 @@ var EasConnector = class {
|
|
|
20794
21014
|
const creds = readEasCredentials(ctx.credentials);
|
|
20795
21015
|
const serviceName = this.config.serviceName ?? this.config.appId;
|
|
20796
21016
|
const maxLookbackMs = this.config.maxLookbackMs ?? DEFAULT_MAX_LOOKBACK_MS6;
|
|
20797
|
-
const sinceIso =
|
|
21017
|
+
const sinceIso = boundedSinceIso3(ctx.since, /* @__PURE__ */ new Date(), maxLookbackMs);
|
|
20798
21018
|
const builds = await fetchErroredBuilds(creds.token, this.config, this.fetchImpl);
|
|
20799
21019
|
const fresh = builds.filter((b) => isBuildSince(b, sinceIso));
|
|
20800
21020
|
const maxLogBytes = this.config.maxLogBytes ?? DEFAULT_MAX_LOG_BYTES;
|
|
@@ -21025,6 +21245,40 @@ var PROVIDER_DISPATCH = {
|
|
|
21025
21245
|
});
|
|
21026
21246
|
}
|
|
21027
21247
|
},
|
|
21248
|
+
"gcp-lb": {
|
|
21249
|
+
provider: "gcp-lb",
|
|
21250
|
+
// Like cloud-run, gcp-lb reads both projectId and accessToken from the
|
|
21251
|
+
// credential; the single-string form maps to the secret (the token), and the
|
|
21252
|
+
// required-fields check below catches a projectId that was never supplied.
|
|
21253
|
+
primaryCredentialKey: "accessToken",
|
|
21254
|
+
requiredCredentialFields: ["projectId", "accessToken"],
|
|
21255
|
+
requiredOptionFields: [],
|
|
21256
|
+
build(graph, options) {
|
|
21257
|
+
return createGcpLbConnector(graph, options);
|
|
21258
|
+
},
|
|
21259
|
+
// POST entries:list with pageSize 1 — the exact surface poll() reads, so the
|
|
21260
|
+
// probe checks the actual `logging.logEntries.list` permission the connector
|
|
21261
|
+
// needs. This is the same Cloud Logging read-verdict cloud-run's validate
|
|
21262
|
+
// uses (a lighter GET on logs.list would instead check `logging.logs.list`,
|
|
21263
|
+
// falsely rejecting a correctly-scoped custom role carrying only
|
|
21264
|
+
// `logging.logEntries.list`). A 2xx means the token can list log entries;
|
|
21265
|
+
// 401/403 means the provider rejected it.
|
|
21266
|
+
validate({ credentials, fetchImpl }) {
|
|
21267
|
+
const projectId = String(credentials.projectId ?? "");
|
|
21268
|
+
return authProbe({
|
|
21269
|
+
provider: "gcp-lb",
|
|
21270
|
+
accountKey: projectId || "validate",
|
|
21271
|
+
url: "https://logging.googleapis.com/v2/entries:list",
|
|
21272
|
+
token: String(credentials.accessToken ?? ""),
|
|
21273
|
+
init: {
|
|
21274
|
+
method: "POST",
|
|
21275
|
+
headers: { "Content-Type": "application/json" },
|
|
21276
|
+
body: JSON.stringify({ resourceNames: [`projects/${projectId}`], pageSize: 1 })
|
|
21277
|
+
},
|
|
21278
|
+
...fetchImpl ? { fetchImpl } : {}
|
|
21279
|
+
});
|
|
21280
|
+
}
|
|
21281
|
+
},
|
|
21028
21282
|
render: {
|
|
21029
21283
|
provider: "render",
|
|
21030
21284
|
primaryCredentialKey: "token",
|
|
@@ -21490,11 +21744,11 @@ function registerRoutes(scope, ctx) {
|
|
|
21490
21744
|
const candidates = req2.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
21491
21745
|
const parsed = [];
|
|
21492
21746
|
for (const c of candidates) {
|
|
21493
|
-
const r =
|
|
21747
|
+
const r = import_types97.DivergenceTypeSchema.safeParse(c);
|
|
21494
21748
|
if (!r.success) {
|
|
21495
21749
|
return reply.code(400).send({
|
|
21496
21750
|
error: `unknown divergence type "${c}"`,
|
|
21497
|
-
allowed:
|
|
21751
|
+
allowed: import_types97.DivergenceTypeSchema.options
|
|
21498
21752
|
});
|
|
21499
21753
|
}
|
|
21500
21754
|
parsed.push(r.data);
|
|
@@ -21856,7 +22110,7 @@ function registerRoutes(scope, ctx) {
|
|
|
21856
22110
|
const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
|
|
21857
22111
|
let violations = await log.readAll();
|
|
21858
22112
|
if (req2.query.severity) {
|
|
21859
|
-
const sev =
|
|
22113
|
+
const sev = import_types97.PolicySeveritySchema.safeParse(req2.query.severity);
|
|
21860
22114
|
if (!sev.success) {
|
|
21861
22115
|
return reply.code(400).send({
|
|
21862
22116
|
error: "invalid severity",
|
|
@@ -21895,7 +22149,7 @@ function registerRoutes(scope, ctx) {
|
|
|
21895
22149
|
scope.post("/policies/check", async (req2, reply) => {
|
|
21896
22150
|
const proj = resolveProject(registry, req2, reply, ctx.bootstrap, ctx.singleProject);
|
|
21897
22151
|
if (!proj) return;
|
|
21898
|
-
const parsed =
|
|
22152
|
+
const parsed = import_types97.PoliciesCheckBodySchema.safeParse(req2.body ?? {});
|
|
21899
22153
|
if (!parsed.success) {
|
|
21900
22154
|
return reply.code(400).send({
|
|
21901
22155
|
error: "invalid /policies/check body",
|
|
@@ -22236,7 +22490,7 @@ function unroutedErrorsPath(neatHome4) {
|
|
|
22236
22490
|
}
|
|
22237
22491
|
|
|
22238
22492
|
// src/daemon.ts
|
|
22239
|
-
var
|
|
22493
|
+
var import_types98 = require("@neat.is/types");
|
|
22240
22494
|
function daemonJsonPath(scanPath) {
|
|
22241
22495
|
return import_node_path75.default.join(scanPath, "neat-out", "daemon.json");
|
|
22242
22496
|
}
|
|
@@ -22375,7 +22629,7 @@ function spanBelongsToSingleProject(graph, project, serviceName) {
|
|
|
22375
22629
|
if (!serviceName) return true;
|
|
22376
22630
|
if (serviceNameMatchesProject(serviceName, project)) return true;
|
|
22377
22631
|
return graph.someNode(
|
|
22378
|
-
(_id, attrs) => attrs.type ===
|
|
22632
|
+
(_id, attrs) => attrs.type === import_types98.NodeType.ServiceNode && attrs.name === serviceName
|
|
22379
22633
|
);
|
|
22380
22634
|
}
|
|
22381
22635
|
async function bootstrapProject(entry2, connectors = [], neatHome4) {
|