@neat.is/core 0.9.5-dev.20260825 → 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/neatd.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
reconcileDaemonRecordSync,
|
|
4
4
|
startDaemon
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-4SLKQNG7.js";
|
|
6
6
|
import {
|
|
7
7
|
listProjects,
|
|
8
8
|
registryPath
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-DGAI4VOE.js";
|
|
10
10
|
import {
|
|
11
11
|
BindAuthorityError,
|
|
12
12
|
__require
|
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_types97 = require("@neat.is/types");
|
|
791
791
|
|
|
792
792
|
// src/extend/index.ts
|
|
793
793
|
init_cjs_shims();
|
|
@@ -19799,9 +19799,229 @@ function createCloudRunConnector(graph, config = {}) {
|
|
|
19799
19799
|
};
|
|
19800
19800
|
}
|
|
19801
19801
|
|
|
19802
|
+
// src/connectors/gcp-lb/index.ts
|
|
19803
|
+
init_cjs_shims();
|
|
19804
|
+
|
|
19805
|
+
// src/connectors/gcp-lb/client.ts
|
|
19806
|
+
init_cjs_shims();
|
|
19807
|
+
function gcpLbRequestLogName(projectId) {
|
|
19808
|
+
return `projects/${projectId}/logs/requests`;
|
|
19809
|
+
}
|
|
19810
|
+
function buildGcpLbEntriesFilter(projectId, sinceIso) {
|
|
19811
|
+
return [
|
|
19812
|
+
`logName = "${gcpLbRequestLogName(projectId)}"`,
|
|
19813
|
+
`resource.type = "${GCP_LB_RESOURCE_TYPE}"`,
|
|
19814
|
+
'httpRequest.requestMethod != ""',
|
|
19815
|
+
`timestamp >= "${sinceIso}"`
|
|
19816
|
+
].join(" AND ");
|
|
19817
|
+
}
|
|
19818
|
+
var GCP_LB_RESOURCE_TYPE = "http_load_balancer";
|
|
19819
|
+
var DEFAULT_LOOKBACK_MS3 = 24 * 60 * 60 * 1e3;
|
|
19820
|
+
var ENTRIES_LIST_URL3 = "https://logging.googleapis.com/v2/entries:list";
|
|
19821
|
+
var PAGE_SIZE3 = 1e3;
|
|
19822
|
+
var MAX_PAGES3 = 20;
|
|
19823
|
+
async function fetchGcpLbRequestLogEntries(creds, sinceIso, apiUrl = ENTRIES_LIST_URL3) {
|
|
19824
|
+
const filter = buildGcpLbEntriesFilter(creds.projectId, sinceIso);
|
|
19825
|
+
const out = [];
|
|
19826
|
+
let pageToken;
|
|
19827
|
+
for (let page = 0; page < MAX_PAGES3; page++) {
|
|
19828
|
+
const body = {
|
|
19829
|
+
resourceNames: [`projects/${creds.projectId}`],
|
|
19830
|
+
filter,
|
|
19831
|
+
orderBy: "timestamp asc",
|
|
19832
|
+
pageSize: PAGE_SIZE3,
|
|
19833
|
+
...pageToken ? { pageToken } : {}
|
|
19834
|
+
};
|
|
19835
|
+
const res = await junctionFetch(
|
|
19836
|
+
apiUrl,
|
|
19837
|
+
{
|
|
19838
|
+
method: "POST",
|
|
19839
|
+
headers: {
|
|
19840
|
+
...bearerAuthHeader(creds.accessToken),
|
|
19841
|
+
"Content-Type": "application/json"
|
|
19842
|
+
},
|
|
19843
|
+
body: JSON.stringify(body)
|
|
19844
|
+
},
|
|
19845
|
+
// accountKey: the GCP project id — one customer's Cloud Logging quota is
|
|
19846
|
+
// scoped per GCP project (ADR-131's per-(provider, accountKey) rate-limit
|
|
19847
|
+
// bucket), the same key Cloud Run's and Firebase's connectors use.
|
|
19848
|
+
{ provider: "gcp-lb", accountKey: creds.projectId }
|
|
19849
|
+
);
|
|
19850
|
+
if (!res.ok) {
|
|
19851
|
+
throw new Error(`Cloud Logging entries.list failed: ${res.status} ${res.statusText}`);
|
|
19852
|
+
}
|
|
19853
|
+
const json = await res.json();
|
|
19854
|
+
if (Array.isArray(json.entries)) out.push(...json.entries);
|
|
19855
|
+
if (!json.nextPageToken) break;
|
|
19856
|
+
pageToken = json.nextPageToken;
|
|
19857
|
+
}
|
|
19858
|
+
return out;
|
|
19859
|
+
}
|
|
19860
|
+
|
|
19861
|
+
// src/connectors/gcp-lb/map.ts
|
|
19862
|
+
init_cjs_shims();
|
|
19863
|
+
|
|
19864
|
+
// src/connectors/gcp-lb/types.ts
|
|
19865
|
+
init_cjs_shims();
|
|
19866
|
+
function readGcpLbCredentials(raw) {
|
|
19867
|
+
const projectId = raw["projectId"];
|
|
19868
|
+
const accessToken = raw["accessToken"];
|
|
19869
|
+
if (typeof projectId !== "string" || projectId.length === 0) {
|
|
19870
|
+
throw new Error("gcp-lb connector: credentials.projectId must be a non-empty string");
|
|
19871
|
+
}
|
|
19872
|
+
if (typeof accessToken !== "string" || accessToken.length === 0) {
|
|
19873
|
+
throw new Error("gcp-lb connector: credentials.accessToken must be a non-empty string");
|
|
19874
|
+
}
|
|
19875
|
+
return { projectId, accessToken };
|
|
19876
|
+
}
|
|
19877
|
+
var GCP_LB_TARGET_KIND = "http_load_balancer";
|
|
19878
|
+
var FIELD_SEP3 = "\0";
|
|
19879
|
+
function packGcpLbTargetName(identity) {
|
|
19880
|
+
return [identity.backendServiceName, identity.method, identity.path].join(FIELD_SEP3);
|
|
19881
|
+
}
|
|
19882
|
+
function parseGcpLbTargetName(targetName) {
|
|
19883
|
+
const firstSep = targetName.indexOf(FIELD_SEP3);
|
|
19884
|
+
if (firstSep === -1) return null;
|
|
19885
|
+
const backendServiceName = targetName.slice(0, firstSep);
|
|
19886
|
+
const rest = targetName.slice(firstSep + 1);
|
|
19887
|
+
const secondSep = rest.indexOf(FIELD_SEP3);
|
|
19888
|
+
if (secondSep === -1) return null;
|
|
19889
|
+
const method = rest.slice(0, secondSep);
|
|
19890
|
+
const path76 = rest.slice(secondSep + 1);
|
|
19891
|
+
if (!backendServiceName || !method || !path76) return null;
|
|
19892
|
+
return { backendServiceName, method, path: path76 };
|
|
19893
|
+
}
|
|
19894
|
+
|
|
19895
|
+
// src/connectors/gcp-lb/map.ts
|
|
19896
|
+
var GCP_LB_RESOURCE_TYPE2 = "http_load_balancer";
|
|
19897
|
+
function pathFromRequestUrl3(requestUrl) {
|
|
19898
|
+
if (typeof requestUrl !== "string" || requestUrl.length === 0) return null;
|
|
19899
|
+
if (requestUrl.startsWith("/")) {
|
|
19900
|
+
const withoutQuery = requestUrl.split("?")[0];
|
|
19901
|
+
return withoutQuery && withoutQuery.length > 0 ? withoutQuery : "/";
|
|
19902
|
+
}
|
|
19903
|
+
try {
|
|
19904
|
+
const candidate = requestUrl.startsWith("//") ? `https:${requestUrl}` : requestUrl;
|
|
19905
|
+
const parsed = new URL(candidate);
|
|
19906
|
+
return parsed.pathname || "/";
|
|
19907
|
+
} catch {
|
|
19908
|
+
return null;
|
|
19909
|
+
}
|
|
19910
|
+
}
|
|
19911
|
+
var ERROR_STATUS_THRESHOLD5 = 500;
|
|
19912
|
+
function mapLogEntryToSignal3(entry) {
|
|
19913
|
+
if (!entry || typeof entry !== "object") return null;
|
|
19914
|
+
if (entry.resource?.type !== GCP_LB_RESOURCE_TYPE2) return null;
|
|
19915
|
+
const backendServiceName = entry.resource?.labels?.["backend_service_name"];
|
|
19916
|
+
if (typeof backendServiceName !== "string" || backendServiceName.length === 0) return null;
|
|
19917
|
+
const req = entry.httpRequest;
|
|
19918
|
+
if (!req) return null;
|
|
19919
|
+
if (typeof req.requestMethod !== "string" || req.requestMethod.length === 0) return null;
|
|
19920
|
+
const method = req.requestMethod.toUpperCase();
|
|
19921
|
+
const path76 = pathFromRequestUrl3(req.requestUrl);
|
|
19922
|
+
if (path76 === null) return null;
|
|
19923
|
+
const timestamp = entry.timestamp;
|
|
19924
|
+
if (typeof timestamp !== "string" || timestamp.length === 0) return null;
|
|
19925
|
+
const isError = typeof req.status === "number" && req.status >= ERROR_STATUS_THRESHOLD5;
|
|
19926
|
+
return {
|
|
19927
|
+
targetKind: GCP_LB_TARGET_KIND,
|
|
19928
|
+
targetName: packGcpLbTargetName({ backendServiceName, method, path: path76 }),
|
|
19929
|
+
callCount: 1,
|
|
19930
|
+
errorCount: isError ? 1 : 0,
|
|
19931
|
+
lastObservedIso: timestamp
|
|
19932
|
+
};
|
|
19933
|
+
}
|
|
19934
|
+
function mapLogEntriesToSignals3(entries) {
|
|
19935
|
+
const out = [];
|
|
19936
|
+
for (const entry of entries) {
|
|
19937
|
+
const signal = mapLogEntryToSignal3(entry);
|
|
19938
|
+
if (signal) out.push(signal);
|
|
19939
|
+
}
|
|
19940
|
+
return out;
|
|
19941
|
+
}
|
|
19942
|
+
|
|
19943
|
+
// src/connectors/gcp-lb/resolve.ts
|
|
19944
|
+
init_cjs_shims();
|
|
19945
|
+
var import_types82 = require("@neat.is/types");
|
|
19946
|
+
var GCP_LB_BACKEND_INFRA_KIND = "gcp-lb-backend";
|
|
19947
|
+
function findMatchingRouteNode3(graph, serviceName, method, normalizedPath) {
|
|
19948
|
+
let found = null;
|
|
19949
|
+
graph.forEachNode((_id, attrs) => {
|
|
19950
|
+
if (found) return;
|
|
19951
|
+
const node = attrs;
|
|
19952
|
+
if (node.type !== import_types82.NodeType.RouteNode) return;
|
|
19953
|
+
const route = attrs;
|
|
19954
|
+
if (route.service !== serviceName || !route.pathTemplate) return;
|
|
19955
|
+
if (normalizePathTemplate(route.pathTemplate) !== normalizedPath) return;
|
|
19956
|
+
const routeMethod = route.method.toUpperCase();
|
|
19957
|
+
if (routeMethod !== "ALL" && routeMethod !== method) return;
|
|
19958
|
+
found = route.id;
|
|
19959
|
+
});
|
|
19960
|
+
return found;
|
|
19961
|
+
}
|
|
19962
|
+
function createGcpLbResolveTarget(graph, config) {
|
|
19963
|
+
return (signal) => {
|
|
19964
|
+
if (signal.targetKind !== GCP_LB_TARGET_KIND) return null;
|
|
19965
|
+
const identity = parseGcpLbTargetName(signal.targetName);
|
|
19966
|
+
if (!identity) return null;
|
|
19967
|
+
const { backendServiceName, method, path: path76 } = identity;
|
|
19968
|
+
const mappedService = config.backendServiceMap?.[backendServiceName];
|
|
19969
|
+
if (mappedService) {
|
|
19970
|
+
const routeNodeId = findMatchingRouteNode3(
|
|
19971
|
+
graph,
|
|
19972
|
+
mappedService,
|
|
19973
|
+
method,
|
|
19974
|
+
normalizePathTemplate(path76)
|
|
19975
|
+
);
|
|
19976
|
+
if (routeNodeId) {
|
|
19977
|
+
return { targetNodeId: routeNodeId, serviceName: mappedService, edgeType: import_types82.EdgeType.CALLS };
|
|
19978
|
+
}
|
|
19979
|
+
}
|
|
19980
|
+
return {
|
|
19981
|
+
targetNodeId: (0, import_types82.infraId)(GCP_LB_BACKEND_INFRA_KIND, backendServiceName),
|
|
19982
|
+
serviceName: mappedService ?? backendServiceName,
|
|
19983
|
+
edgeType: import_types82.EdgeType.CALLS,
|
|
19984
|
+
ensureInfraNode: {
|
|
19985
|
+
kind: GCP_LB_BACKEND_INFRA_KIND,
|
|
19986
|
+
name: backendServiceName,
|
|
19987
|
+
provider: "gcp-lb"
|
|
19988
|
+
}
|
|
19989
|
+
};
|
|
19990
|
+
};
|
|
19991
|
+
}
|
|
19992
|
+
|
|
19993
|
+
// src/connectors/gcp-lb/index.ts
|
|
19994
|
+
var GcpLbConnector = class {
|
|
19995
|
+
constructor(config = {}) {
|
|
19996
|
+
this.config = config;
|
|
19997
|
+
}
|
|
19998
|
+
config;
|
|
19999
|
+
provider = "gcp-lb";
|
|
20000
|
+
async poll(ctx) {
|
|
20001
|
+
const creds = readGcpLbCredentials(ctx.credentials);
|
|
20002
|
+
const maxLookbackMs = this.config.maxLookbackMs ?? DEFAULT_LOOKBACK_MS3;
|
|
20003
|
+
const sinceIso = boundedSinceIso2(ctx.since, /* @__PURE__ */ new Date(), maxLookbackMs);
|
|
20004
|
+
const entries = await fetchGcpLbRequestLogEntries(creds, sinceIso, this.config.apiUrl);
|
|
20005
|
+
return mapLogEntriesToSignals3(entries);
|
|
20006
|
+
}
|
|
20007
|
+
};
|
|
20008
|
+
function boundedSinceIso2(since, now, maxLookbackMs) {
|
|
20009
|
+
const floor = new Date(now.getTime() - maxLookbackMs);
|
|
20010
|
+
if (!since) return floor.toISOString();
|
|
20011
|
+
const sinceMs = new Date(since).getTime();
|
|
20012
|
+
if (Number.isNaN(sinceMs)) return floor.toISOString();
|
|
20013
|
+
return sinceMs < floor.getTime() ? floor.toISOString() : new Date(sinceMs).toISOString();
|
|
20014
|
+
}
|
|
20015
|
+
function createGcpLbConnector(graph, config = {}) {
|
|
20016
|
+
return {
|
|
20017
|
+
connector: new GcpLbConnector(config),
|
|
20018
|
+
resolveTarget: createGcpLbResolveTarget(graph, config)
|
|
20019
|
+
};
|
|
20020
|
+
}
|
|
20021
|
+
|
|
19802
20022
|
// src/connectors/render/index.ts
|
|
19803
20023
|
init_cjs_shims();
|
|
19804
|
-
var
|
|
20024
|
+
var import_types85 = require("@neat.is/types");
|
|
19805
20025
|
|
|
19806
20026
|
// src/connectors/render/types.ts
|
|
19807
20027
|
init_cjs_shims();
|
|
@@ -19879,7 +20099,7 @@ function buildRenderRouteIndex(graph, serviceName) {
|
|
|
19879
20099
|
const out = [];
|
|
19880
20100
|
graph.forEachNode((_id, attrs) => {
|
|
19881
20101
|
const node = attrs;
|
|
19882
|
-
if (node.type !==
|
|
20102
|
+
if (node.type !== import_types85.NodeType.RouteNode) return;
|
|
19883
20103
|
const route = attrs;
|
|
19884
20104
|
if (route.service !== serviceName) return;
|
|
19885
20105
|
out.push({
|
|
@@ -19964,7 +20184,7 @@ function mapRenderRequestLogsToSignals(entries, routeIndex) {
|
|
|
19964
20184
|
function createRenderResolveTarget(config) {
|
|
19965
20185
|
return (signal) => {
|
|
19966
20186
|
if (signal.targetKind === ROUTE_TARGET_KIND2) {
|
|
19967
|
-
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType:
|
|
20187
|
+
return { targetNodeId: signal.targetName, serviceName: config.serviceName, edgeType: import_types85.EdgeType.CALLS };
|
|
19968
20188
|
}
|
|
19969
20189
|
return null;
|
|
19970
20190
|
};
|
|
@@ -20102,21 +20322,21 @@ function mapInsightsToSignals(rows, observedAtIso) {
|
|
|
20102
20322
|
|
|
20103
20323
|
// src/connectors/planetscale/resolve.ts
|
|
20104
20324
|
init_cjs_shims();
|
|
20105
|
-
var
|
|
20325
|
+
var import_types89 = require("@neat.is/types");
|
|
20106
20326
|
var PLANETSCALE_DATABASE_KIND = "planetscale-database";
|
|
20107
20327
|
function createPlanetscaleResolveTarget(graph, config) {
|
|
20108
20328
|
const databaseName = `${config.organization}/${config.database}`;
|
|
20109
20329
|
return (signal, _ctx) => {
|
|
20110
20330
|
if (signal.targetKind !== PLANETSCALE_SQL_TABLE_TARGET_KIND || !signal.targetName) return null;
|
|
20111
|
-
const tableId = (0,
|
|
20331
|
+
const tableId = (0, import_types89.infraId)("sql-table", signal.targetName);
|
|
20112
20332
|
if (graph.hasNode(tableId)) {
|
|
20113
|
-
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType:
|
|
20333
|
+
return { targetNodeId: tableId, serviceName: config.serviceName, edgeType: import_types89.EdgeType.CALLS };
|
|
20114
20334
|
}
|
|
20115
|
-
const providerId = (0,
|
|
20335
|
+
const providerId = (0, import_types89.infraId)(PLANETSCALE_DATABASE_KIND, databaseName);
|
|
20116
20336
|
return {
|
|
20117
20337
|
targetNodeId: providerId,
|
|
20118
20338
|
serviceName: config.serviceName,
|
|
20119
|
-
edgeType:
|
|
20339
|
+
edgeType: import_types89.EdgeType.CALLS,
|
|
20120
20340
|
ensureInfraNode: { kind: PLANETSCALE_DATABASE_KIND, name: databaseName, provider: "planetscale" }
|
|
20121
20341
|
};
|
|
20122
20342
|
};
|
|
@@ -20182,13 +20402,13 @@ function isTransientFailure(err) {
|
|
|
20182
20402
|
if (code && INTERNAL_ERROR_CODE.test(code)) return true;
|
|
20183
20403
|
return false;
|
|
20184
20404
|
}
|
|
20185
|
-
var
|
|
20405
|
+
var FIELD_SEP4 = "\0";
|
|
20186
20406
|
var EAS_TARGET_KIND = "eas-build";
|
|
20187
20407
|
function packEasTargetName(identity) {
|
|
20188
|
-
return [identity.serviceName, identity.phase].join(
|
|
20408
|
+
return [identity.serviceName, identity.phase].join(FIELD_SEP4);
|
|
20189
20409
|
}
|
|
20190
20410
|
function parseEasTargetName(targetName) {
|
|
20191
|
-
const sep = targetName.indexOf(
|
|
20411
|
+
const sep = targetName.indexOf(FIELD_SEP4);
|
|
20192
20412
|
if (sep === -1) return null;
|
|
20193
20413
|
const serviceName = targetName.slice(0, sep);
|
|
20194
20414
|
const phase = targetName.slice(sep + 1);
|
|
@@ -20381,7 +20601,7 @@ function mapBuildsToSignals(builds, serviceName) {
|
|
|
20381
20601
|
|
|
20382
20602
|
// src/connectors/eas/resolve.ts
|
|
20383
20603
|
init_cjs_shims();
|
|
20384
|
-
var
|
|
20604
|
+
var import_types94 = require("@neat.is/types");
|
|
20385
20605
|
var NO_ENV2 = "unknown";
|
|
20386
20606
|
var EAS_JSON_PHASES = /* @__PURE__ */ new Set(["READ_EAS_JSON"]);
|
|
20387
20607
|
var APP_CONFIG_PHASES = /* @__PURE__ */ new Set([
|
|
@@ -20397,8 +20617,8 @@ function configBasenamesForPhase(phase) {
|
|
|
20397
20617
|
function configNodeService(graph, configNodeId) {
|
|
20398
20618
|
for (const edgeId of graph.inboundEdges(configNodeId)) {
|
|
20399
20619
|
const edge = graph.getEdgeAttributes(edgeId);
|
|
20400
|
-
if (edge.type !==
|
|
20401
|
-
const parsed = (0,
|
|
20620
|
+
if (edge.type !== import_types94.EdgeType.CONFIGURED_BY) continue;
|
|
20621
|
+
const parsed = (0, import_types94.parseFileId)(edge.source);
|
|
20402
20622
|
if (parsed) return parsed.service;
|
|
20403
20623
|
}
|
|
20404
20624
|
return null;
|
|
@@ -20409,7 +20629,7 @@ function findConfigNode(graph, basenames, serviceName) {
|
|
|
20409
20629
|
graph.forEachNode((id, attrs) => {
|
|
20410
20630
|
if (scoped) return;
|
|
20411
20631
|
const node = attrs;
|
|
20412
|
-
if (node.type !==
|
|
20632
|
+
if (node.type !== import_types94.NodeType.ConfigNode) return;
|
|
20413
20633
|
if (typeof node.name !== "string" || !basenames.includes(node.name)) return;
|
|
20414
20634
|
if (anyMatch === null) anyMatch = id;
|
|
20415
20635
|
if (configNodeService(graph, id) === serviceName) scoped = id;
|
|
@@ -20426,13 +20646,13 @@ function createEasResolveTarget(graph) {
|
|
|
20426
20646
|
if (basenames.length > 0) {
|
|
20427
20647
|
const configNodeId = findConfigNode(graph, basenames, serviceName);
|
|
20428
20648
|
if (configNodeId) {
|
|
20429
|
-
return { targetNodeId: configNodeId, serviceName, edgeType:
|
|
20649
|
+
return { targetNodeId: configNodeId, serviceName, edgeType: import_types94.EdgeType.CALLS };
|
|
20430
20650
|
}
|
|
20431
20651
|
}
|
|
20432
20652
|
return {
|
|
20433
20653
|
targetNodeId: resolveFusedServiceId(graph, serviceName, NO_ENV2),
|
|
20434
20654
|
serviceName,
|
|
20435
|
-
edgeType:
|
|
20655
|
+
edgeType: import_types94.EdgeType.CALLS
|
|
20436
20656
|
};
|
|
20437
20657
|
};
|
|
20438
20658
|
}
|
|
@@ -20444,7 +20664,7 @@ function isBuildSince(build, sinceIso) {
|
|
|
20444
20664
|
if (Number.isNaN(t) || Number.isNaN(s)) return true;
|
|
20445
20665
|
return t > s;
|
|
20446
20666
|
}
|
|
20447
|
-
function
|
|
20667
|
+
function boundedSinceIso3(since, now, maxLookbackMs) {
|
|
20448
20668
|
const floor = new Date(now.getTime() - maxLookbackMs);
|
|
20449
20669
|
if (!since) return floor.toISOString();
|
|
20450
20670
|
const sinceMs = new Date(since).getTime();
|
|
@@ -20463,7 +20683,7 @@ var EasConnector = class {
|
|
|
20463
20683
|
const creds = readEasCredentials(ctx.credentials);
|
|
20464
20684
|
const serviceName = this.config.serviceName ?? this.config.appId;
|
|
20465
20685
|
const maxLookbackMs = this.config.maxLookbackMs ?? DEFAULT_MAX_LOOKBACK_MS6;
|
|
20466
|
-
const sinceIso =
|
|
20686
|
+
const sinceIso = boundedSinceIso3(ctx.since, /* @__PURE__ */ new Date(), maxLookbackMs);
|
|
20467
20687
|
const builds = await fetchErroredBuilds(creds.token, this.config, this.fetchImpl);
|
|
20468
20688
|
const fresh = builds.filter((b) => isBuildSince(b, sinceIso));
|
|
20469
20689
|
const maxLogBytes = this.config.maxLogBytes ?? DEFAULT_MAX_LOG_BYTES;
|
|
@@ -20694,6 +20914,40 @@ var PROVIDER_DISPATCH = {
|
|
|
20694
20914
|
});
|
|
20695
20915
|
}
|
|
20696
20916
|
},
|
|
20917
|
+
"gcp-lb": {
|
|
20918
|
+
provider: "gcp-lb",
|
|
20919
|
+
// Like cloud-run, gcp-lb reads both projectId and accessToken from the
|
|
20920
|
+
// credential; the single-string form maps to the secret (the token), and the
|
|
20921
|
+
// required-fields check below catches a projectId that was never supplied.
|
|
20922
|
+
primaryCredentialKey: "accessToken",
|
|
20923
|
+
requiredCredentialFields: ["projectId", "accessToken"],
|
|
20924
|
+
requiredOptionFields: [],
|
|
20925
|
+
build(graph, options) {
|
|
20926
|
+
return createGcpLbConnector(graph, options);
|
|
20927
|
+
},
|
|
20928
|
+
// POST entries:list with pageSize 1 — the exact surface poll() reads, so the
|
|
20929
|
+
// probe checks the actual `logging.logEntries.list` permission the connector
|
|
20930
|
+
// needs. This is the same Cloud Logging read-verdict cloud-run's validate
|
|
20931
|
+
// uses (a lighter GET on logs.list would instead check `logging.logs.list`,
|
|
20932
|
+
// falsely rejecting a correctly-scoped custom role carrying only
|
|
20933
|
+
// `logging.logEntries.list`). A 2xx means the token can list log entries;
|
|
20934
|
+
// 401/403 means the provider rejected it.
|
|
20935
|
+
validate({ credentials, fetchImpl }) {
|
|
20936
|
+
const projectId = String(credentials.projectId ?? "");
|
|
20937
|
+
return authProbe({
|
|
20938
|
+
provider: "gcp-lb",
|
|
20939
|
+
accountKey: projectId || "validate",
|
|
20940
|
+
url: "https://logging.googleapis.com/v2/entries:list",
|
|
20941
|
+
token: String(credentials.accessToken ?? ""),
|
|
20942
|
+
init: {
|
|
20943
|
+
method: "POST",
|
|
20944
|
+
headers: { "Content-Type": "application/json" },
|
|
20945
|
+
body: JSON.stringify({ resourceNames: [`projects/${projectId}`], pageSize: 1 })
|
|
20946
|
+
},
|
|
20947
|
+
...fetchImpl ? { fetchImpl } : {}
|
|
20948
|
+
});
|
|
20949
|
+
}
|
|
20950
|
+
},
|
|
20697
20951
|
render: {
|
|
20698
20952
|
provider: "render",
|
|
20699
20953
|
primaryCredentialKey: "token",
|
|
@@ -21113,11 +21367,11 @@ function registerRoutes(scope, ctx) {
|
|
|
21113
21367
|
const candidates = req.query.type.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
21114
21368
|
const parsed = [];
|
|
21115
21369
|
for (const c of candidates) {
|
|
21116
|
-
const r =
|
|
21370
|
+
const r = import_types97.DivergenceTypeSchema.safeParse(c);
|
|
21117
21371
|
if (!r.success) {
|
|
21118
21372
|
return reply.code(400).send({
|
|
21119
21373
|
error: `unknown divergence type "${c}"`,
|
|
21120
|
-
allowed:
|
|
21374
|
+
allowed: import_types97.DivergenceTypeSchema.options
|
|
21121
21375
|
});
|
|
21122
21376
|
}
|
|
21123
21377
|
parsed.push(r.data);
|
|
@@ -21479,7 +21733,7 @@ function registerRoutes(scope, ctx) {
|
|
|
21479
21733
|
const log = new PolicyViolationsLog(proj.paths.policyViolationsPath);
|
|
21480
21734
|
let violations = await log.readAll();
|
|
21481
21735
|
if (req.query.severity) {
|
|
21482
|
-
const sev =
|
|
21736
|
+
const sev = import_types97.PolicySeveritySchema.safeParse(req.query.severity);
|
|
21483
21737
|
if (!sev.success) {
|
|
21484
21738
|
return reply.code(400).send({
|
|
21485
21739
|
error: "invalid severity",
|
|
@@ -21518,7 +21772,7 @@ function registerRoutes(scope, ctx) {
|
|
|
21518
21772
|
scope.post("/policies/check", async (req, reply) => {
|
|
21519
21773
|
const proj = resolveProject(registry, req, reply, ctx.bootstrap, ctx.singleProject);
|
|
21520
21774
|
if (!proj) return;
|
|
21521
|
-
const parsed =
|
|
21775
|
+
const parsed = import_types97.PoliciesCheckBodySchema.safeParse(req.body ?? {});
|
|
21522
21776
|
if (!parsed.success) {
|
|
21523
21777
|
return reply.code(400).send({
|
|
21524
21778
|
error: "invalid /policies/check body",
|