@datasynx/agentic-ai-cartography 2.10.0 → 2.12.1
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/README.md +142 -2
- package/dist/api-bin.js +2 -2
- package/dist/{chunk-YVV6NIT2.js → chunk-LO6YFS6H.js} +2 -1
- package/dist/{chunk-ASCA3UFM.js → chunk-OIDAXUW5.js} +340 -204
- package/dist/chunk-OIDAXUW5.js.map +1 -0
- package/dist/{chunk-W4Q3TXHR.js → chunk-PD67MOKR.js} +2 -2
- package/dist/cli.js +97 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +241 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +126 -3
- package/dist/index.d.ts +126 -3
- package/dist/index.js +217 -16
- package/dist/index.js.map +1 -1
- package/dist/mcp-bin.js +2 -2
- package/llms-full.txt +305 -25
- package/package.json +1 -1
- package/server.json +2 -2
- package/dist/chunk-ASCA3UFM.js.map +0 -1
- /package/dist/{chunk-YVV6NIT2.js.map → chunk-LO6YFS6H.js.map} +0 -0
- /package/dist/{chunk-W4Q3TXHR.js.map → chunk-PD67MOKR.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -4652,6 +4652,8 @@ function reversalKey(orgKey) {
|
|
|
4652
4652
|
// src/anonymize.ts
|
|
4653
4653
|
var PRIVATE_IP = /\b(?:10(?:\.\d{1,3}){3}|192\.168(?:\.\d{1,3}){2}|172\.(?:1[6-9]|2\d|3[01])(?:\.\d{1,3}){2})\b/g;
|
|
4654
4654
|
var HOSTNAME = /\b(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}\b/gi;
|
|
4655
|
+
var BARE_INTERNAL_HOST = /^[a-z0-9]+(?:-[a-z0-9]+)+$|^[a-z]+\d+$|^\d+[a-z]+$/i;
|
|
4656
|
+
var ANON_TOKEN = /^anon:(?:host|user|path|ip):[a-z2-7]+$/;
|
|
4655
4657
|
var POSIX_PATH = /(?:^|(?<=\s|=|:|"|'|\())(\/[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)+)/g;
|
|
4656
4658
|
var WIN_PATH = /\b[A-Za-z]:\\[A-Za-z0-9._\\-]+/g;
|
|
4657
4659
|
var B32_ALPHABET = "abcdefghijklmnopqrstuvwxyz234567";
|
|
@@ -4706,8 +4708,18 @@ function pseudonymizeString(s, orgKey, db) {
|
|
|
4706
4708
|
(_m, user, host2) => `${pseudonymizeFragment(user, "user", orgKey, db)}@${pseudonymizeFragment(host2, "host", orgKey, db)}`
|
|
4707
4709
|
);
|
|
4708
4710
|
out = out.replace(HOSTNAME, (m) => pseudonymizeFragment(m, "host", orgKey, db));
|
|
4711
|
+
const trimmed = out.trim();
|
|
4712
|
+
if (out === s && !ANON_TOKEN.test(trimmed) && BARE_INTERNAL_HOST.test(trimmed)) {
|
|
4713
|
+
out = pseudonymizeFragment(trimmed, "host", orgKey, db);
|
|
4714
|
+
}
|
|
4709
4715
|
return out;
|
|
4710
4716
|
}
|
|
4717
|
+
function pseudonymizeId(id, orgKey, db) {
|
|
4718
|
+
const segments = id.split(":");
|
|
4719
|
+
if (segments.length <= 1) return pseudonymizeString(id, orgKey, db);
|
|
4720
|
+
const [type, ...rest] = segments;
|
|
4721
|
+
return [type, ...rest.map((seg) => pseudonymizeString(seg, orgKey, db))].join(":");
|
|
4722
|
+
}
|
|
4711
4723
|
function pseudonymize(value, orgKey, db) {
|
|
4712
4724
|
if (typeof value === "string") return pseudonymizeString(value, orgKey, db);
|
|
4713
4725
|
if (Array.isArray(value)) return value.map((v) => pseudonymize(v, orgKey, db));
|
|
@@ -4734,8 +4746,6 @@ var FQDN = /\b(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}\b/gi;
|
|
|
4734
4746
|
var POSIX_PATH2 = /(?:^|(?<=\s|=|:|"|'|\())(\/[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)+)/g;
|
|
4735
4747
|
var WIN_PATH2 = /\b[A-Za-z]:\\[A-Za-z0-9._\\-]+/g;
|
|
4736
4748
|
var HOME_USER = /(?:\/home\/|\/Users\/|[A-Za-z]:\\Users\\)([A-Za-z0-9._-]+)/g;
|
|
4737
|
-
var BARE_INTERNAL_HOST = /^[a-z0-9]+(?:-[a-z0-9]+)+$|^[a-z]+\d+$|^\d+[a-z]+$/i;
|
|
4738
|
-
var ANON_TOKEN = /^anon:(?:host|user|path|ip):[a-z2-7]+$/;
|
|
4739
4749
|
function violationsInString(s, path) {
|
|
4740
4750
|
const out = [];
|
|
4741
4751
|
const trimmed = s.trim();
|
|
@@ -5125,9 +5135,10 @@ function resolveEffectiveLevel(node, policy) {
|
|
|
5125
5135
|
function applySharingLevel(node, level, orgKey, db) {
|
|
5126
5136
|
if (level === "none") return null;
|
|
5127
5137
|
if (level === "full") return { ...node, metadata: { ...node.metadata ?? {} }, tags: [...node.tags ?? []] };
|
|
5138
|
+
const { globalId: _g, contentHash: _h, ...rest } = node;
|
|
5128
5139
|
return {
|
|
5129
|
-
...
|
|
5130
|
-
id:
|
|
5140
|
+
...rest,
|
|
5141
|
+
id: pseudonymizeId(node.id, orgKey, db),
|
|
5131
5142
|
name: pseudonymizeString(node.name, orgKey, db),
|
|
5132
5143
|
metadata: pseudonymize(node.metadata ?? {}, orgKey, db),
|
|
5133
5144
|
tags: (node.tags ?? []).map((t) => pseudonymizeString(t, orgKey, db))
|
|
@@ -5979,7 +5990,7 @@ function correlateTopology(nodes, _edges = []) {
|
|
|
5979
5990
|
|
|
5980
5991
|
// src/mcp/server.ts
|
|
5981
5992
|
var SERVER_NAME = "cartography";
|
|
5982
|
-
var SERVER_VERSION = "2.
|
|
5993
|
+
var SERVER_VERSION = "2.12.1";
|
|
5983
5994
|
var SERVICE_TYPES = NODE_TYPE_GROUPS.web;
|
|
5984
5995
|
var DATA_TYPES = NODE_TYPE_GROUPS.data;
|
|
5985
5996
|
var lexicalSearch = async (db, sessionId, query, opts) => db.searchNodes(sessionId, query, { types: opts.types, limit: opts.limit }).map((node) => ({ node }));
|
|
@@ -7389,9 +7400,132 @@ var serviceConfigScanner = {
|
|
|
7389
7400
|
}
|
|
7390
7401
|
};
|
|
7391
7402
|
|
|
7403
|
+
// src/scanners/terraform.ts
|
|
7404
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
7405
|
+
var TYPE_RULES = [
|
|
7406
|
+
[/(db_instance|_rds|sql_database|sql_instance|database_instance|cosmosdb|dynamodb|spanner|bigtable|documentdb|redshift)/, "database_server"],
|
|
7407
|
+
[/(elasticache|_redis|memcached|memorystore)/, "cache_server"],
|
|
7408
|
+
[/(s3_bucket|storage_bucket|gcs_bucket|storage_account|_blob)/, "database"],
|
|
7409
|
+
[/(_sqs|_queue|servicebus_queue)/, "queue"],
|
|
7410
|
+
[/(_sns|_topic|pubsub_topic|servicebus_topic)/, "topic"],
|
|
7411
|
+
[/(kafka|_msk|event_hub|kinesis)/, "message_broker"],
|
|
7412
|
+
[/(_eks|_gke|_aks|kubernetes_cluster|container_cluster)/, "k8s_cluster"],
|
|
7413
|
+
[/(ecs_|_container|fargate)/, "container"],
|
|
7414
|
+
[/(lambda|cloud_function|cloudfunctions|function_app|cloud_run)/, "web_service"],
|
|
7415
|
+
[/(_lb$|load_balancer|_alb|_elb|application_gateway)/, "web_service"],
|
|
7416
|
+
[/(api_gateway|apigateway)/, "api_endpoint"],
|
|
7417
|
+
[/(_instance|virtual_machine|_vm$|compute_instance)/, "host"]
|
|
7418
|
+
];
|
|
7419
|
+
function terraformTypeToNode(tfType) {
|
|
7420
|
+
const t = tfType.toLowerCase();
|
|
7421
|
+
for (const [re, nt] of TYPE_RULES) if (re.test(t)) return nt;
|
|
7422
|
+
return "unknown";
|
|
7423
|
+
}
|
|
7424
|
+
var IDENTITY_ATTRS = ["id", "arn", "region", "location", "instance_type", "engine", "machine_type"];
|
|
7425
|
+
var OWNER_TAGS = ["Owner", "owner", "Team", "team"];
|
|
7426
|
+
var SAFE_TAG_KEYS = /* @__PURE__ */ new Set(["Name", "name", "Owner", "owner", "Team", "team", "Env", "env", "Environment", "environment", "Service", "service", "Component", "component", "App", "app", "Project", "project", "Tier", "tier", "Role", "role"]);
|
|
7427
|
+
var SECRET_KEY = /pass|secret|token|key|pwd|cred|private/i;
|
|
7428
|
+
function attrTags(tags) {
|
|
7429
|
+
if (!tags || typeof tags !== "object") return [];
|
|
7430
|
+
return Object.entries(tags).filter(([k]) => SAFE_TAG_KEYS.has(k) && !SECRET_KEY.test(k)).map(([k, v]) => `${k}:${redactSecrets(String(v))}`);
|
|
7431
|
+
}
|
|
7432
|
+
function parseTerraformState(json2) {
|
|
7433
|
+
let state;
|
|
7434
|
+
try {
|
|
7435
|
+
state = JSON.parse(json2);
|
|
7436
|
+
} catch {
|
|
7437
|
+
return { nodes: [], edges: [] };
|
|
7438
|
+
}
|
|
7439
|
+
const resources = Array.isArray(state?.resources) ? state.resources : [];
|
|
7440
|
+
const nodes = [];
|
|
7441
|
+
const edges = [];
|
|
7442
|
+
const addrToId = /* @__PURE__ */ new Map();
|
|
7443
|
+
for (const raw of resources) {
|
|
7444
|
+
const r = raw;
|
|
7445
|
+
if (r.mode && r.mode !== "managed") continue;
|
|
7446
|
+
if (typeof r.type !== "string" || typeof r.name !== "string") continue;
|
|
7447
|
+
const address = `${r.type}.${r.name}`;
|
|
7448
|
+
const nt = terraformTypeToNode(r.type);
|
|
7449
|
+
const id = `${nt}:terraform:${address}`;
|
|
7450
|
+
if (addrToId.has(address)) continue;
|
|
7451
|
+
addrToId.set(address, id);
|
|
7452
|
+
const inst = Array.isArray(r.instances) ? r.instances[0] : void 0;
|
|
7453
|
+
const attrs = inst?.attributes ?? {};
|
|
7454
|
+
const identity = { source: "terraform", tfType: r.type };
|
|
7455
|
+
for (const k of IDENTITY_ATTRS) if (attrs[k] !== void 0) identity[k] = attrs[k];
|
|
7456
|
+
const owner = OWNER_TAGS.map((k) => attrs.tags?.[k]).find((v) => typeof v === "string");
|
|
7457
|
+
nodes.push({
|
|
7458
|
+
id,
|
|
7459
|
+
type: nt,
|
|
7460
|
+
name: address,
|
|
7461
|
+
discoveredVia: "terraform-state",
|
|
7462
|
+
confidence: 0.9,
|
|
7463
|
+
// IaC is authoritative declared intent.
|
|
7464
|
+
metadata: redactValue(identity),
|
|
7465
|
+
tags: attrTags(attrs.tags),
|
|
7466
|
+
...owner ? { owner } : {}
|
|
7467
|
+
});
|
|
7468
|
+
}
|
|
7469
|
+
for (const raw of resources) {
|
|
7470
|
+
const r = raw;
|
|
7471
|
+
if (r.mode && r.mode !== "managed") continue;
|
|
7472
|
+
if (typeof r.type !== "string" || typeof r.name !== "string") continue;
|
|
7473
|
+
const srcId = addrToId.get(`${r.type}.${r.name}`);
|
|
7474
|
+
if (!srcId) continue;
|
|
7475
|
+
const inst = Array.isArray(r.instances) ? r.instances[0] : void 0;
|
|
7476
|
+
const deps = Array.isArray(inst?.dependencies) ? inst.dependencies : [];
|
|
7477
|
+
for (const dep of deps) {
|
|
7478
|
+
if (typeof dep !== "string") continue;
|
|
7479
|
+
const tgtId = addrToId.get(dep) ?? addrToId.get(dep.split("[")[0]);
|
|
7480
|
+
if (!tgtId || tgtId === srcId) continue;
|
|
7481
|
+
edges.push({ sourceId: srcId, targetId: tgtId, relationship: "depends_on", evidence: evidenceLine("config-declared", `terraform depends_on ${dep}`), confidence: 0.85 });
|
|
7482
|
+
}
|
|
7483
|
+
}
|
|
7484
|
+
return { nodes, edges };
|
|
7485
|
+
}
|
|
7486
|
+
function stateDirs() {
|
|
7487
|
+
return [".", "./terraform", "./infra", "./infrastructure", "./deploy", "./terraform/environments"];
|
|
7488
|
+
}
|
|
7489
|
+
function hintPath(hint) {
|
|
7490
|
+
if (!hint) return void 0;
|
|
7491
|
+
const m = /(?:^|[\s,])tfstate=([^\s,]+)/.exec(hint);
|
|
7492
|
+
return m ? m[1] : void 0;
|
|
7493
|
+
}
|
|
7494
|
+
function resolveStatePath(ctx) {
|
|
7495
|
+
const explicit = hintPath(ctx.hint);
|
|
7496
|
+
if (explicit) return explicit;
|
|
7497
|
+
const found = (ctx.findFiles ?? findFiles)(stateDirs(), ["*.tfstate"], 4, 20).split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
7498
|
+
return found[0];
|
|
7499
|
+
}
|
|
7500
|
+
function readStateFile(path) {
|
|
7501
|
+
try {
|
|
7502
|
+
return readFileSync4(path, "utf8");
|
|
7503
|
+
} catch {
|
|
7504
|
+
return "";
|
|
7505
|
+
}
|
|
7506
|
+
}
|
|
7507
|
+
var terraformScanner = {
|
|
7508
|
+
id: "terraform-state",
|
|
7509
|
+
title: "Terraform state (IaC)",
|
|
7510
|
+
platforms: "all",
|
|
7511
|
+
// No shell commands — the state file is read directly via node:fs, so an
|
|
7512
|
+
// operator-supplied path can never inject a command (no `cat "${path}"` interpolation).
|
|
7513
|
+
detect(ctx) {
|
|
7514
|
+
return resolveStatePath(ctx) !== void 0;
|
|
7515
|
+
},
|
|
7516
|
+
async scan(ctx) {
|
|
7517
|
+
const path = resolveStatePath(ctx);
|
|
7518
|
+
if (!path) return { nodes: [], edges: [] };
|
|
7519
|
+
const json2 = (ctx.readFile ?? readStateFile)(path);
|
|
7520
|
+
if (!json2) return { nodes: [], edges: [] };
|
|
7521
|
+
const result = parseTerraformState(json2);
|
|
7522
|
+
return { ...result, report: `terraform-state: ${result.nodes.length} resources, ${result.edges.length} dependencies from ${path}` };
|
|
7523
|
+
}
|
|
7524
|
+
};
|
|
7525
|
+
|
|
7392
7526
|
// src/scanners/registry.ts
|
|
7393
7527
|
function defaultRegistry() {
|
|
7394
|
-
return new ScannerRegistry().register(bookmarksScanner).register(installedAppsScanner).register(portsScanner).register(cloudAwsScanner).register(cloudGcpScanner).register(cloudAzureScanner).register(k8sScanner).register(databasesScanner).register(connectionsScanner).register(serviceConfigScanner);
|
|
7528
|
+
return new ScannerRegistry().register(bookmarksScanner).register(installedAppsScanner).register(portsScanner).register(cloudAwsScanner).register(cloudGcpScanner).register(cloudAzureScanner).register(k8sScanner).register(databasesScanner).register(connectionsScanner).register(serviceConfigScanner).register(terraformScanner);
|
|
7395
7529
|
}
|
|
7396
7530
|
|
|
7397
7531
|
// src/scanners/loader.ts
|
|
@@ -8759,13 +8893,13 @@ var AuthConfigSchema = z9.object({
|
|
|
8759
8893
|
});
|
|
8760
8894
|
|
|
8761
8895
|
// src/api/start.ts
|
|
8762
|
-
import { readFileSync as
|
|
8896
|
+
import { readFileSync as readFileSync5 } from "fs";
|
|
8763
8897
|
import { dirname as dirname3, resolve } from "path";
|
|
8764
8898
|
import { fileURLToPath } from "url";
|
|
8765
8899
|
function readVersion() {
|
|
8766
8900
|
try {
|
|
8767
8901
|
const dir = import.meta.dirname ?? dirname3(fileURLToPath(import.meta.url));
|
|
8768
|
-
return JSON.parse(
|
|
8902
|
+
return JSON.parse(readFileSync5(resolve(dir, "..", "package.json"), "utf-8")).version ?? "0.0.0";
|
|
8769
8903
|
} catch {
|
|
8770
8904
|
return "0.0.0";
|
|
8771
8905
|
}
|
|
@@ -8896,7 +9030,7 @@ function defaultServerEntry(opts = {}) {
|
|
|
8896
9030
|
}
|
|
8897
9031
|
|
|
8898
9032
|
// src/installer/install.ts
|
|
8899
|
-
import { mkdirSync as mkdirSync4, readFileSync as
|
|
9033
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync6, writeFileSync as writeFileSync3, existsSync as existsSync4 } from "fs";
|
|
8900
9034
|
import { dirname as dirname4 } from "path";
|
|
8901
9035
|
import { homedir as homedir3 } from "os";
|
|
8902
9036
|
function currentOs() {
|
|
@@ -8913,7 +9047,7 @@ function planInstall(spec, ctx, opts) {
|
|
|
8913
9047
|
throw new Error(`${spec.label} does not support the "${ctx.scope}" scope.`);
|
|
8914
9048
|
}
|
|
8915
9049
|
const fileExists = existsSync4(path);
|
|
8916
|
-
const before = fileExists ?
|
|
9050
|
+
const before = fileExists ? readFileSync6(path, "utf8") : "";
|
|
8917
9051
|
const existing = parseConfig(before, spec.format);
|
|
8918
9052
|
const merged = spec.apply(existing, opts.serverName ?? DEFAULT_SERVER_NAME, opts.entry);
|
|
8919
9053
|
const after = serializeConfig(merged, spec.format);
|
|
@@ -9778,8 +9912,65 @@ Use ask_user when you need context from the user.`;
|
|
|
9778
9912
|
}
|
|
9779
9913
|
}
|
|
9780
9914
|
|
|
9915
|
+
// src/k8s/operator.ts
|
|
9916
|
+
function k8sRegistry() {
|
|
9917
|
+
return new ScannerRegistry().register(k8sScanner);
|
|
9918
|
+
}
|
|
9919
|
+
function isInCluster(env = process.env) {
|
|
9920
|
+
return typeof env["KUBERNETES_SERVICE_HOST"] === "string" && env["KUBERNETES_SERVICE_HOST"].length > 0;
|
|
9921
|
+
}
|
|
9922
|
+
function pruneToRetention(db, keep, tenant) {
|
|
9923
|
+
const stale = db.getSessions(tenant).slice(Math.max(1, keep));
|
|
9924
|
+
for (const s of stale) db.deleteSession(s.id);
|
|
9925
|
+
return stale.length;
|
|
9926
|
+
}
|
|
9927
|
+
async function runOperatorCycle(db, config, opts = {}) {
|
|
9928
|
+
const sessionId = db.createSession("discover", config);
|
|
9929
|
+
const discover = opts.discover ?? ((d, s) => runLocalDiscovery(d, s, { registry: k8sRegistry() }));
|
|
9930
|
+
const res = await discover(db, sessionId);
|
|
9931
|
+
const sess = db.getSession(sessionId);
|
|
9932
|
+
if (sess && !sess.name) db.setSessionName(sessionId, deriveSessionName(db.getGraphSummary(sessionId), sess.startedAt));
|
|
9933
|
+
const driftFn = opts.drift ?? ((d, c) => runDrift(d, c));
|
|
9934
|
+
const drift = await driftFn(db, config);
|
|
9935
|
+
pruneToRetention(db, opts.retain ?? 10, normalizeTenant(config.organization));
|
|
9936
|
+
return { sessionId, nodes: res.nodes, edges: res.edges, drift };
|
|
9937
|
+
}
|
|
9938
|
+
async function runOperator(db, config, opts = {}) {
|
|
9939
|
+
const log2 = opts.log ?? ((m) => process.stderr.write(m + "\n"));
|
|
9940
|
+
const intervalMs = opts.intervalMs ?? 5 * 6e4;
|
|
9941
|
+
const sleep = opts.sleep ?? ((ms) => new Promise((resolve3) => {
|
|
9942
|
+
if (opts.signal?.aborted) {
|
|
9943
|
+
resolve3();
|
|
9944
|
+
return;
|
|
9945
|
+
}
|
|
9946
|
+
const t = setTimeout(() => {
|
|
9947
|
+
opts.signal?.removeEventListener?.("abort", onAbort);
|
|
9948
|
+
resolve3();
|
|
9949
|
+
}, ms);
|
|
9950
|
+
const onAbort = () => {
|
|
9951
|
+
clearTimeout(t);
|
|
9952
|
+
resolve3();
|
|
9953
|
+
};
|
|
9954
|
+
opts.signal?.addEventListener?.("abort", onAbort, { once: true });
|
|
9955
|
+
}));
|
|
9956
|
+
log2(`Cartograph Kubernetes operator (in-cluster: ${isInCluster()}, interval: ${Math.round(intervalMs / 1e3)}s${opts.once ? ", single pass" : ""})`);
|
|
9957
|
+
for (; ; ) {
|
|
9958
|
+
try {
|
|
9959
|
+
const c = await runOperatorCycle(db, config, opts);
|
|
9960
|
+
log2(
|
|
9961
|
+
`reconcile: session ${c.sessionId} \u2014 ${c.nodes} nodes, ${c.edges} edges` + (c.drift ? `, drift ${c.drift.severity} (${c.drift.items.length} change${c.drift.items.length === 1 ? "" : "s"})` : ", no drift")
|
|
9962
|
+
);
|
|
9963
|
+
} catch (err) {
|
|
9964
|
+
log2(`reconcile failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
9965
|
+
}
|
|
9966
|
+
if (opts.once || opts.signal?.aborted) return;
|
|
9967
|
+
await sleep(intervalMs);
|
|
9968
|
+
if (opts.signal?.aborted) return;
|
|
9969
|
+
}
|
|
9970
|
+
}
|
|
9971
|
+
|
|
9781
9972
|
// src/cost.ts
|
|
9782
|
-
import { readFileSync as
|
|
9973
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
9783
9974
|
import { resolve as resolve2 } from "path";
|
|
9784
9975
|
function splitCsvLine(line) {
|
|
9785
9976
|
const out = [];
|
|
@@ -9858,7 +10049,7 @@ var CsvCostSource = class {
|
|
|
9858
10049
|
}
|
|
9859
10050
|
id;
|
|
9860
10051
|
async fetch() {
|
|
9861
|
-
const text =
|
|
10052
|
+
const text = readFileSync7(resolve2(this.opts.filePath), "utf-8");
|
|
9862
10053
|
const records = parseCostCsv(text);
|
|
9863
10054
|
const match = this.opts.match ?? "nodeId";
|
|
9864
10055
|
const out = /* @__PURE__ */ new Map();
|
|
@@ -11623,7 +11814,7 @@ function formatComplianceText(report) {
|
|
|
11623
11814
|
}
|
|
11624
11815
|
|
|
11625
11816
|
// src/config.ts
|
|
11626
|
-
import { readFileSync as
|
|
11817
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
11627
11818
|
var ConfigError = class extends Error {
|
|
11628
11819
|
constructor(message) {
|
|
11629
11820
|
super(message);
|
|
@@ -11648,7 +11839,7 @@ function loadConfig(path) {
|
|
|
11648
11839
|
function readConfigFile(path) {
|
|
11649
11840
|
let raw;
|
|
11650
11841
|
try {
|
|
11651
|
-
raw =
|
|
11842
|
+
raw = readFileSync8(path, "utf-8");
|
|
11652
11843
|
} catch (err) {
|
|
11653
11844
|
throw new ConfigError(
|
|
11654
11845
|
`Cannot read config file ${path}: ${err instanceof Error ? err.message : String(err)}`
|
|
@@ -12006,14 +12197,14 @@ function runSyncClassify(db, sessionId, config, opts = {}) {
|
|
|
12006
12197
|
|
|
12007
12198
|
// src/preflight.ts
|
|
12008
12199
|
import { execSync as execSync2 } from "child_process";
|
|
12009
|
-
import { existsSync as existsSync5, readFileSync as
|
|
12200
|
+
import { existsSync as existsSync5, readFileSync as readFileSync9 } from "fs";
|
|
12010
12201
|
import { join as join6 } from "path";
|
|
12011
12202
|
function isOAuthLoggedIn() {
|
|
12012
12203
|
const home = process.env.HOME ?? process.env.USERPROFILE ?? "/tmp";
|
|
12013
12204
|
const credFile = join6(home, ".claude", ".credentials.json");
|
|
12014
12205
|
if (!existsSync5(credFile)) return false;
|
|
12015
12206
|
try {
|
|
12016
|
-
const creds = JSON.parse(
|
|
12207
|
+
const creds = JSON.parse(readFileSync9(credFile, "utf8"));
|
|
12017
12208
|
const oauth = creds["claudeAiOauth"];
|
|
12018
12209
|
return typeof oauth?.["accessToken"] === "string" && oauth["accessToken"].length > 0;
|
|
12019
12210
|
} catch {
|
|
@@ -12065,9 +12256,11 @@ function checkClaudePrerequisites() {
|
|
|
12065
12256
|
}
|
|
12066
12257
|
export {
|
|
12067
12258
|
ACTIONS,
|
|
12259
|
+
ANON_TOKEN,
|
|
12068
12260
|
ActionSchema,
|
|
12069
12261
|
AuthConfigSchema,
|
|
12070
12262
|
AuthorizationError,
|
|
12263
|
+
BARE_INTERNAL_HOST,
|
|
12071
12264
|
CLIENTS,
|
|
12072
12265
|
CONFIDENCE,
|
|
12073
12266
|
CORRELATION_CONFIDENCE,
|
|
@@ -12231,11 +12424,13 @@ export {
|
|
|
12231
12424
|
hostname,
|
|
12232
12425
|
ingestEnvelope,
|
|
12233
12426
|
installedAppsScanner,
|
|
12427
|
+
isInCluster,
|
|
12234
12428
|
isLoopbackHost,
|
|
12235
12429
|
isPersonalHost,
|
|
12236
12430
|
isReadOnlyCommand,
|
|
12237
12431
|
isRemembered,
|
|
12238
12432
|
isSecureWebhookUrl,
|
|
12433
|
+
k8sRegistry,
|
|
12239
12434
|
k8sScanner,
|
|
12240
12435
|
keyMetaOf,
|
|
12241
12436
|
layoutClusters,
|
|
@@ -12272,6 +12467,7 @@ export {
|
|
|
12272
12467
|
parseNginxUpstreams,
|
|
12273
12468
|
parseNlQuery,
|
|
12274
12469
|
parseScanHint,
|
|
12470
|
+
parseTerraformState,
|
|
12275
12471
|
pixelToHex,
|
|
12276
12472
|
planInstall,
|
|
12277
12473
|
portsScanner,
|
|
@@ -12279,6 +12475,7 @@ export {
|
|
|
12279
12475
|
previewShare,
|
|
12280
12476
|
pseudonymize,
|
|
12281
12477
|
pseudonymizeFragment,
|
|
12478
|
+
pseudonymizeId,
|
|
12282
12479
|
pseudonymizeString,
|
|
12283
12480
|
pushDeltas,
|
|
12284
12481
|
readConfigFile,
|
|
@@ -12301,6 +12498,8 @@ export {
|
|
|
12301
12498
|
runHttp,
|
|
12302
12499
|
runLocalDiscovery,
|
|
12303
12500
|
runOnce,
|
|
12501
|
+
runOperator,
|
|
12502
|
+
runOperatorCycle,
|
|
12304
12503
|
runStdio,
|
|
12305
12504
|
runSyncClassify,
|
|
12306
12505
|
safeEnv,
|
|
@@ -12321,6 +12520,8 @@ export {
|
|
|
12321
12520
|
stableStringify,
|
|
12322
12521
|
startApi,
|
|
12323
12522
|
stripSensitive,
|
|
12523
|
+
terraformScanner,
|
|
12524
|
+
terraformTypeToNode,
|
|
12324
12525
|
timingSafeEqual,
|
|
12325
12526
|
toBackstageEntities,
|
|
12326
12527
|
validateScanner,
|