@neat.is/core 0.9.20-dev.20260922 → 0.9.20
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-KIV7OB2K.js → chunk-NFJ4W5T6.js} +168 -7
- package/dist/chunk-NFJ4W5T6.js.map +1 -0
- package/dist/{chunk-F7I3G4KC.js → chunk-SK2FEJKB.js} +39 -2
- package/dist/chunk-SK2FEJKB.js.map +1 -0
- package/dist/cli.cjs +260 -14
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +89 -8
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +200 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +2 -2
- package/dist/neatd.cjs +200 -6
- package/dist/neatd.cjs.map +1 -1
- package/dist/neatd.js +2 -2
- package/dist/server.cjs +155 -7
- package/dist/server.cjs.map +1 -1
- package/dist/server.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-F7I3G4KC.js.map +0 -1
- package/dist/chunk-KIV7OB2K.js.map +0 -1
package/dist/neatd.js
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import {
|
|
3
3
|
reconcileDaemonRecordSync,
|
|
4
4
|
startDaemon
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-SK2FEJKB.js";
|
|
6
6
|
import {
|
|
7
7
|
listProjects,
|
|
8
8
|
registryPath
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-NFJ4W5T6.js";
|
|
10
10
|
import {
|
|
11
11
|
BindAuthorityError,
|
|
12
12
|
__require
|
package/dist/server.cjs
CHANGED
|
@@ -5704,9 +5704,30 @@ function withRecoveredCodeAttrs(attrs, locus) {
|
|
|
5704
5704
|
if (locus.codeLineno !== void 0) attrs[CODE_LINENO_ATTR] = locus.codeLineno;
|
|
5705
5705
|
return attrs;
|
|
5706
5706
|
}
|
|
5707
|
+
var SENSITIVE_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
5708
|
+
"authorization",
|
|
5709
|
+
"proxy-authorization",
|
|
5710
|
+
"cookie",
|
|
5711
|
+
"set-cookie",
|
|
5712
|
+
"x-api-key",
|
|
5713
|
+
"api-key",
|
|
5714
|
+
"x-auth-token",
|
|
5715
|
+
"x-amz-security-token",
|
|
5716
|
+
"x-csrf-token"
|
|
5717
|
+
]);
|
|
5718
|
+
function attrHeaderName(key) {
|
|
5719
|
+
const lower = key.toLowerCase();
|
|
5720
|
+
const marker = ".header.";
|
|
5721
|
+
const at = lower.lastIndexOf(marker);
|
|
5722
|
+
return at >= 0 ? lower.slice(at + marker.length) : lower;
|
|
5723
|
+
}
|
|
5724
|
+
function isSensitiveAttrKey(key) {
|
|
5725
|
+
return SENSITIVE_HEADER_NAMES.has(attrHeaderName(key));
|
|
5726
|
+
}
|
|
5707
5727
|
function sanitizeAttributes(attrs) {
|
|
5708
5728
|
const out = {};
|
|
5709
5729
|
for (const [k, v] of Object.entries(attrs)) {
|
|
5730
|
+
if (isSensitiveAttrKey(k)) continue;
|
|
5710
5731
|
if (typeof v === "bigint") out[k] = v.toString();
|
|
5711
5732
|
else out[k] = v;
|
|
5712
5733
|
}
|
|
@@ -6262,6 +6283,14 @@ async function readErrorFileTail(errorsPath, maxBytes) {
|
|
|
6262
6283
|
await handle.close();
|
|
6263
6284
|
}
|
|
6264
6285
|
}
|
|
6286
|
+
function redactPersistedAttributes(ev) {
|
|
6287
|
+
if (!ev.attributes) return ev;
|
|
6288
|
+
const scrubbed = sanitizeAttributes(ev.attributes);
|
|
6289
|
+
if (Object.keys(scrubbed).length === Object.keys(ev.attributes).length) return ev;
|
|
6290
|
+
if (Object.keys(scrubbed).length > 0) return { ...ev, attributes: scrubbed };
|
|
6291
|
+
const { attributes: _dropped, ...rest } = ev;
|
|
6292
|
+
return rest;
|
|
6293
|
+
}
|
|
6265
6294
|
async function readErrorEvents(errorsPath, opts) {
|
|
6266
6295
|
let raw;
|
|
6267
6296
|
try {
|
|
@@ -6270,7 +6299,7 @@ async function readErrorEvents(errorsPath, opts) {
|
|
|
6270
6299
|
if (err.code === "ENOENT") return [];
|
|
6271
6300
|
throw err;
|
|
6272
6301
|
}
|
|
6273
|
-
const events = raw.split("\n").filter((line) => line.length > 0).map((line) => JSON.parse(line));
|
|
6302
|
+
const events = raw.split("\n").filter((line) => line.length > 0).map((line) => redactPersistedAttributes(JSON.parse(line)));
|
|
6274
6303
|
const deduped = dedupeIncidents(events);
|
|
6275
6304
|
const cap = opts?.limit !== void 0 && opts.limit > 0 ? Math.min(opts.limit, INCIDENT_READ_MAX_EVENTS) : INCIDENT_READ_MAX_EVENTS;
|
|
6276
6305
|
return deduped.length > cap ? deduped.slice(deduped.length - cap) : deduped;
|
|
@@ -18756,6 +18785,10 @@ async function runConnectorPoll(connector, ctx, graph, resolveTarget) {
|
|
|
18756
18785
|
// src/connectors/registry.ts
|
|
18757
18786
|
init_cjs_shims();
|
|
18758
18787
|
|
|
18788
|
+
// src/connectors/gcp-auth.ts
|
|
18789
|
+
init_cjs_shims();
|
|
18790
|
+
var import_node_crypto3 = require("crypto");
|
|
18791
|
+
|
|
18759
18792
|
// src/connectors/junction.ts
|
|
18760
18793
|
init_cjs_shims();
|
|
18761
18794
|
var buckets = /* @__PURE__ */ new Map();
|
|
@@ -19017,6 +19050,108 @@ async function dbJunction(run, policy) {
|
|
|
19017
19050
|
}
|
|
19018
19051
|
}
|
|
19019
19052
|
|
|
19053
|
+
// src/connectors/gcp-auth.ts
|
|
19054
|
+
var DEFAULT_TOKEN_URI = "https://oauth2.googleapis.com/token";
|
|
19055
|
+
var JWT_BEARER_GRANT = "urn:ietf:params:oauth:grant-type:jwt-bearer";
|
|
19056
|
+
var ASSERTION_LIFETIME_S = 3600;
|
|
19057
|
+
var DEFAULT_REFRESH_SKEW_MS = 6e4;
|
|
19058
|
+
var GCP_LOGGING_READ_SCOPE = "https://www.googleapis.com/auth/logging.read";
|
|
19059
|
+
function parseServiceAccountKey(json) {
|
|
19060
|
+
let raw;
|
|
19061
|
+
try {
|
|
19062
|
+
raw = JSON.parse(json);
|
|
19063
|
+
} catch {
|
|
19064
|
+
throw new Error("gcp service-account key: not valid JSON");
|
|
19065
|
+
}
|
|
19066
|
+
if (!raw || typeof raw !== "object") {
|
|
19067
|
+
throw new Error("gcp service-account key: expected a JSON object");
|
|
19068
|
+
}
|
|
19069
|
+
const obj = raw;
|
|
19070
|
+
const clientEmail = obj["client_email"];
|
|
19071
|
+
const privateKey = obj["private_key"];
|
|
19072
|
+
const projectId = obj["project_id"];
|
|
19073
|
+
if (typeof clientEmail !== "string" || clientEmail.length === 0) {
|
|
19074
|
+
throw new Error("gcp service-account key: missing client_email");
|
|
19075
|
+
}
|
|
19076
|
+
if (typeof privateKey !== "string" || privateKey.length === 0) {
|
|
19077
|
+
throw new Error("gcp service-account key: missing private_key");
|
|
19078
|
+
}
|
|
19079
|
+
if (typeof projectId !== "string" || projectId.length === 0) {
|
|
19080
|
+
throw new Error("gcp service-account key: missing project_id");
|
|
19081
|
+
}
|
|
19082
|
+
const key = { client_email: clientEmail, private_key: privateKey, project_id: projectId };
|
|
19083
|
+
if (typeof obj["token_uri"] === "string" && obj["token_uri"].length > 0) {
|
|
19084
|
+
key.token_uri = obj["token_uri"];
|
|
19085
|
+
}
|
|
19086
|
+
return key;
|
|
19087
|
+
}
|
|
19088
|
+
function base64url(input) {
|
|
19089
|
+
return Buffer.from(input).toString("base64url");
|
|
19090
|
+
}
|
|
19091
|
+
function buildServiceAccountAssertion(key, scope, tokenUri, nowMs) {
|
|
19092
|
+
const iat = Math.floor(nowMs / 1e3);
|
|
19093
|
+
const header = { alg: "RS256", typ: "JWT" };
|
|
19094
|
+
const claims = {
|
|
19095
|
+
iss: key.client_email,
|
|
19096
|
+
scope,
|
|
19097
|
+
aud: tokenUri,
|
|
19098
|
+
iat,
|
|
19099
|
+
exp: iat + ASSERTION_LIFETIME_S
|
|
19100
|
+
};
|
|
19101
|
+
const signingInput = `${base64url(JSON.stringify(header))}.${base64url(JSON.stringify(claims))}`;
|
|
19102
|
+
const signature = (0, import_node_crypto3.createSign)("RSA-SHA256").update(signingInput).end().sign(key.private_key);
|
|
19103
|
+
return `${signingInput}.${base64url(signature)}`;
|
|
19104
|
+
}
|
|
19105
|
+
async function mintGcpAccessToken(key, scope, opts = {}) {
|
|
19106
|
+
const now = opts.now ?? Date.now;
|
|
19107
|
+
const tokenUri = opts.tokenUri ?? key.token_uri ?? DEFAULT_TOKEN_URI;
|
|
19108
|
+
const mintedAtMs = now();
|
|
19109
|
+
const assertion = buildServiceAccountAssertion(key, scope, tokenUri, mintedAtMs);
|
|
19110
|
+
const body = new URLSearchParams({ grant_type: JWT_BEARER_GRANT, assertion }).toString();
|
|
19111
|
+
const res = await junctionFetch(
|
|
19112
|
+
tokenUri,
|
|
19113
|
+
{
|
|
19114
|
+
method: "POST",
|
|
19115
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
19116
|
+
body
|
|
19117
|
+
},
|
|
19118
|
+
// accountKey: the GCP project id — an identifier, safe to log, the same
|
|
19119
|
+
// per-(provider, accountKey) rate-limit bucket key the GCP connectors use.
|
|
19120
|
+
{ provider: "gcp-auth", accountKey: key.project_id, ...opts.fetchImpl ? { fetchImpl: opts.fetchImpl } : {} }
|
|
19121
|
+
);
|
|
19122
|
+
if (!res.ok) {
|
|
19123
|
+
throw new Error(`gcp token mint failed: ${res.status} ${res.statusText}`);
|
|
19124
|
+
}
|
|
19125
|
+
const json = await res.json();
|
|
19126
|
+
const accessToken = json.access_token;
|
|
19127
|
+
if (typeof accessToken !== "string" || accessToken.length === 0) {
|
|
19128
|
+
throw new Error("gcp token mint returned no access_token");
|
|
19129
|
+
}
|
|
19130
|
+
const expiresInS = typeof json.expires_in === "number" && json.expires_in > 0 ? json.expires_in : ASSERTION_LIFETIME_S;
|
|
19131
|
+
return { accessToken, expiresAtMs: mintedAtMs + expiresInS * 1e3 };
|
|
19132
|
+
}
|
|
19133
|
+
function createGcpTokenSource(key, scope, opts = {}) {
|
|
19134
|
+
const now = opts.now ?? Date.now;
|
|
19135
|
+
const skewMs = opts.refreshSkewMs ?? DEFAULT_REFRESH_SKEW_MS;
|
|
19136
|
+
let cached = null;
|
|
19137
|
+
let inFlight = null;
|
|
19138
|
+
const fresh = () => cached !== null && now() < cached.expiresAtMs - skewMs;
|
|
19139
|
+
return async () => {
|
|
19140
|
+
if (!fresh()) {
|
|
19141
|
+
if (!inFlight) {
|
|
19142
|
+
inFlight = mintGcpAccessToken(key, scope, opts).then((minted) => {
|
|
19143
|
+
cached = minted;
|
|
19144
|
+
return minted;
|
|
19145
|
+
}).finally(() => {
|
|
19146
|
+
inFlight = null;
|
|
19147
|
+
});
|
|
19148
|
+
}
|
|
19149
|
+
await inFlight;
|
|
19150
|
+
}
|
|
19151
|
+
return { projectId: key.project_id, accessToken: cached.accessToken };
|
|
19152
|
+
};
|
|
19153
|
+
}
|
|
19154
|
+
|
|
19020
19155
|
// src/connectors/supabase/index.ts
|
|
19021
19156
|
init_cjs_shims();
|
|
19022
19157
|
|
|
@@ -19883,7 +20018,7 @@ var import_types73 = require("@neat.is/types");
|
|
|
19883
20018
|
|
|
19884
20019
|
// src/connectors/cloudflare/client.ts
|
|
19885
20020
|
init_cjs_shims();
|
|
19886
|
-
var
|
|
20021
|
+
var import_node_crypto4 = require("crypto");
|
|
19887
20022
|
var DEFAULT_BASE_URL = "https://api.cloudflare.com/client/v4";
|
|
19888
20023
|
var DEFAULT_EVENT_LIMIT = 1e3;
|
|
19889
20024
|
async function queryWorkerInvocations(ctx, config, window, fetchImpl = fetch) {
|
|
@@ -19896,7 +20031,7 @@ async function queryWorkerInvocations(ctx, config, window, fetchImpl = fetch) {
|
|
|
19896
20031
|
const body = {
|
|
19897
20032
|
// Cloudflare's schema requires an identifier per query even for an
|
|
19898
20033
|
// ad-hoc, unsaved one — a fresh id per tick, never reused.
|
|
19899
|
-
queryId: `neat-connector-${(0,
|
|
20034
|
+
queryId: `neat-connector-${(0, import_node_crypto4.randomUUID)()}`,
|
|
19900
20035
|
timeframe: { from: window.fromMs, to: window.toMs },
|
|
19901
20036
|
view: "events",
|
|
19902
20037
|
limit: config.eventLimit ?? DEFAULT_EVENT_LIMIT,
|
|
@@ -21898,7 +22033,8 @@ var PUSH_PROVIDER_DISPATCH = {
|
|
|
21898
22033
|
function isPushProvider(provider) {
|
|
21899
22034
|
return provider in PUSH_PROVIDER_DISPATCH;
|
|
21900
22035
|
}
|
|
21901
|
-
|
|
22036
|
+
var GCP_SERVICE_ACCOUNT_PROVIDERS = /* @__PURE__ */ new Set(["cloud-run", "gcp-lb", "firebase"]);
|
|
22037
|
+
function resolveEntryCredentials(dispatch, entry, env, fetchImpl) {
|
|
21902
22038
|
let credentials;
|
|
21903
22039
|
try {
|
|
21904
22040
|
const resolved = resolveCredential(entry.credential, env);
|
|
@@ -21907,6 +22043,15 @@ function resolveEntryCredentials(dispatch, entry, env) {
|
|
|
21907
22043
|
if (err instanceof EnvRefUnsetError) return { ok: false, kind: "unset-env", reason: err.message };
|
|
21908
22044
|
return { ok: false, kind: "error", reason: err.message };
|
|
21909
22045
|
}
|
|
22046
|
+
if (GCP_SERVICE_ACCOUNT_PROVIDERS.has(entry.provider) && typeof credentials.serviceAccountKey === "string" && credentials.serviceAccountKey.length > 0) {
|
|
22047
|
+
try {
|
|
22048
|
+
const key = parseServiceAccountKey(credentials.serviceAccountKey);
|
|
22049
|
+
const source = createGcpTokenSource(key, GCP_LOGGING_READ_SCOPE, fetchImpl ? { fetchImpl } : {});
|
|
22050
|
+
return { ok: true, credentials: { projectId: key.project_id }, refreshCredentials: source };
|
|
22051
|
+
} catch (err) {
|
|
22052
|
+
return { ok: false, kind: "error", reason: err.message };
|
|
22053
|
+
}
|
|
22054
|
+
}
|
|
21910
22055
|
const missingCreds = dispatch.requiredCredentialFields.filter((k) => !credentials[k]);
|
|
21911
22056
|
if (missingCreds.length > 0) {
|
|
21912
22057
|
return {
|
|
@@ -21956,7 +22101,10 @@ function buildRegistration(entry, graph, env = process.env) {
|
|
|
21956
22101
|
connector: built.connector,
|
|
21957
22102
|
credentials,
|
|
21958
22103
|
resolveTarget: built.resolveTarget,
|
|
21959
|
-
...intervalMs !== void 0 ? { intervalMs } : {}
|
|
22104
|
+
...intervalMs !== void 0 ? { intervalMs } : {},
|
|
22105
|
+
// A refreshable credential (ADR-230) resolves to a per-tick token source; carry it so the daemon wires
|
|
22106
|
+
// it to the poll loop's `refreshCredentials`. Absent for a static credential.
|
|
22107
|
+
...creds.refreshCredentials ? { refreshCredentials: creds.refreshCredentials } : {}
|
|
21960
22108
|
}
|
|
21961
22109
|
};
|
|
21962
22110
|
}
|
|
@@ -22884,7 +23032,7 @@ init_otel_grpc();
|
|
|
22884
23032
|
init_cjs_shims();
|
|
22885
23033
|
var import_node_fs39 = require("fs");
|
|
22886
23034
|
var import_node_path75 = __toESM(require("path"), 1);
|
|
22887
|
-
var
|
|
23035
|
+
var import_node_crypto5 = require("crypto");
|
|
22888
23036
|
var DEFAULT_LIMIT = 10;
|
|
22889
23037
|
var NOMIC_DIM = 768;
|
|
22890
23038
|
var MINI_LM_DIM = 384;
|
|
@@ -22948,7 +23096,7 @@ function embedText(node) {
|
|
|
22948
23096
|
return parts.join(" ");
|
|
22949
23097
|
}
|
|
22950
23098
|
function attrsHash(node) {
|
|
22951
|
-
return (0,
|
|
23099
|
+
return (0, import_node_crypto5.createHash)("sha1").update(embedText(node)).digest("hex").slice(0, 16);
|
|
22952
23100
|
}
|
|
22953
23101
|
function cosine(a, b) {
|
|
22954
23102
|
if (a.length !== b.length) return 0;
|