@ryanstark24/sfgraph-server 1.1.0
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/__tests__/context-cache.test.d.ts +2 -0
- package/dist/__tests__/context-cache.test.d.ts.map +1 -0
- package/dist/__tests__/context-cache.test.js +77 -0
- package/dist/__tests__/context-cache.test.js.map +1 -0
- package/dist/__tests__/context-default-factory.test.d.ts +2 -0
- package/dist/__tests__/context-default-factory.test.d.ts.map +1 -0
- package/dist/__tests__/context-default-factory.test.js +89 -0
- package/dist/__tests__/context-default-factory.test.js.map +1 -0
- package/dist/__tests__/network-egress.test.d.ts +2 -0
- package/dist/__tests__/network-egress.test.d.ts.map +1 -0
- package/dist/__tests__/network-egress.test.js +33 -0
- package/dist/__tests__/network-egress.test.js.map +1 -0
- package/dist/__tests__/shutdown.test.d.ts +2 -0
- package/dist/__tests__/shutdown.test.d.ts.map +1 -0
- package/dist/__tests__/shutdown.test.js +78 -0
- package/dist/__tests__/shutdown.test.js.map +1 -0
- package/dist/__tests__/tool-registry.test.d.ts +2 -0
- package/dist/__tests__/tool-registry.test.d.ts.map +1 -0
- package/dist/__tests__/tool-registry.test.js +21 -0
- package/dist/__tests__/tool-registry.test.js.map +1 -0
- package/dist/__tests__/zod-schema.test.d.ts +2 -0
- package/dist/__tests__/zod-schema.test.d.ts.map +1 -0
- package/dist/__tests__/zod-schema.test.js +15 -0
- package/dist/__tests__/zod-schema.test.js.map +1 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +14 -0
- package/dist/bin.js.map +1 -0
- package/dist/context.d.ts +29 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +202 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +31 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +91 -0
- package/dist/server.js.map +1 -0
- package/dist/shutdown.d.ts +10 -0
- package/dist/shutdown.d.ts.map +1 -0
- package/dist/shutdown.js +43 -0
- package/dist/shutdown.js.map +1 -0
- package/dist/tool-registry.d.ts +31 -0
- package/dist/tool-registry.d.ts.map +1 -0
- package/dist/tool-registry.js +29 -0
- package/dist/tool-registry.js.map +1 -0
- package/dist/tools/__tests__/_fixture.d.ts +29 -0
- package/dist/tools/__tests__/_fixture.d.ts.map +1 -0
- package/dist/tools/__tests__/_fixture.js +59 -0
- package/dist/tools/__tests__/_fixture.js.map +1 -0
- package/dist/tools/__tests__/_runner.d.ts +10 -0
- package/dist/tools/__tests__/_runner.d.ts.map +1 -0
- package/dist/tools/__tests__/_runner.js +12 -0
- package/dist/tools/__tests__/_runner.js.map +1 -0
- package/dist/tools/__tests__/analyze_field.test.d.ts +2 -0
- package/dist/tools/__tests__/analyze_field.test.d.ts.map +1 -0
- package/dist/tools/__tests__/analyze_field.test.js +92 -0
- package/dist/tools/__tests__/analyze_field.test.js.map +1 -0
- package/dist/tools/__tests__/cross_layer_flow_map.test.d.ts +2 -0
- package/dist/tools/__tests__/cross_layer_flow_map.test.d.ts.map +1 -0
- package/dist/tools/__tests__/cross_layer_flow_map.test.js +111 -0
- package/dist/tools/__tests__/cross_layer_flow_map.test.js.map +1 -0
- package/dist/tools/__tests__/cross_org_diff.test.d.ts +2 -0
- package/dist/tools/__tests__/cross_org_diff.test.d.ts.map +1 -0
- package/dist/tools/__tests__/cross_org_diff.test.js +112 -0
- package/dist/tools/__tests__/cross_org_diff.test.js.map +1 -0
- package/dist/tools/__tests__/dead_code_audit.test.d.ts +2 -0
- package/dist/tools/__tests__/dead_code_audit.test.d.ts.map +1 -0
- package/dist/tools/__tests__/dead_code_audit.test.js +71 -0
- package/dist/tools/__tests__/dead_code_audit.test.js.map +1 -0
- package/dist/tools/__tests__/deployment_manifest_gen.test.d.ts +2 -0
- package/dist/tools/__tests__/deployment_manifest_gen.test.d.ts.map +1 -0
- package/dist/tools/__tests__/deployment_manifest_gen.test.js +143 -0
- package/dist/tools/__tests__/deployment_manifest_gen.test.js.map +1 -0
- package/dist/tools/__tests__/dispatcher.test.d.ts +2 -0
- package/dist/tools/__tests__/dispatcher.test.d.ts.map +1 -0
- package/dist/tools/__tests__/dispatcher.test.js +39 -0
- package/dist/tools/__tests__/dispatcher.test.js.map +1 -0
- package/dist/tools/__tests__/explain_code.test.d.ts +2 -0
- package/dist/tools/__tests__/explain_code.test.d.ts.map +1 -0
- package/dist/tools/__tests__/explain_code.test.js +88 -0
- package/dist/tools/__tests__/explain_code.test.js.map +1 -0
- package/dist/tools/__tests__/freshness_report.test.d.ts +2 -0
- package/dist/tools/__tests__/freshness_report.test.d.ts.map +1 -0
- package/dist/tools/__tests__/freshness_report.test.js +103 -0
- package/dist/tools/__tests__/freshness_report.test.js.map +1 -0
- package/dist/tools/__tests__/get_ingest_job.test.d.ts +2 -0
- package/dist/tools/__tests__/get_ingest_job.test.d.ts.map +1 -0
- package/dist/tools/__tests__/get_ingest_job.test.js +42 -0
- package/dist/tools/__tests__/get_ingest_job.test.js.map +1 -0
- package/dist/tools/__tests__/governor_risk_check.test.d.ts +2 -0
- package/dist/tools/__tests__/governor_risk_check.test.d.ts.map +1 -0
- package/dist/tools/__tests__/governor_risk_check.test.js +66 -0
- package/dist/tools/__tests__/governor_risk_check.test.js.map +1 -0
- package/dist/tools/__tests__/impact_from_git_diff.test.d.ts +2 -0
- package/dist/tools/__tests__/impact_from_git_diff.test.d.ts.map +1 -0
- package/dist/tools/__tests__/impact_from_git_diff.test.js +115 -0
- package/dist/tools/__tests__/impact_from_git_diff.test.js.map +1 -0
- package/dist/tools/__tests__/list_orgs.test.d.ts +2 -0
- package/dist/tools/__tests__/list_orgs.test.d.ts.map +1 -0
- package/dist/tools/__tests__/list_orgs.test.js +137 -0
- package/dist/tools/__tests__/list_orgs.test.js.map +1 -0
- package/dist/tools/__tests__/ping.test.d.ts +2 -0
- package/dist/tools/__tests__/ping.test.d.ts.map +1 -0
- package/dist/tools/__tests__/ping.test.js +10 -0
- package/dist/tools/__tests__/ping.test.js.map +1 -0
- package/dist/tools/__tests__/point_in_time_diff.test.d.ts +2 -0
- package/dist/tools/__tests__/point_in_time_diff.test.d.ts.map +1 -0
- package/dist/tools/__tests__/point_in_time_diff.test.js +64 -0
- package/dist/tools/__tests__/point_in_time_diff.test.js.map +1 -0
- package/dist/tools/__tests__/security_audit.test.d.ts +2 -0
- package/dist/tools/__tests__/security_audit.test.d.ts.map +1 -0
- package/dist/tools/__tests__/security_audit.test.js +99 -0
- package/dist/tools/__tests__/security_audit.test.js.map +1 -0
- package/dist/tools/__tests__/snapshot.test.d.ts +2 -0
- package/dist/tools/__tests__/snapshot.test.d.ts.map +1 -0
- package/dist/tools/__tests__/snapshot.test.js +54 -0
- package/dist/tools/__tests__/snapshot.test.js.map +1 -0
- package/dist/tools/__tests__/staleness_check.test.d.ts +2 -0
- package/dist/tools/__tests__/staleness_check.test.d.ts.map +1 -0
- package/dist/tools/__tests__/staleness_check.test.js +51 -0
- package/dist/tools/__tests__/staleness_check.test.js.map +1 -0
- package/dist/tools/__tests__/start_ingest_job.test.d.ts +2 -0
- package/dist/tools/__tests__/start_ingest_job.test.d.ts.map +1 -0
- package/dist/tools/__tests__/start_ingest_job.test.js +55 -0
- package/dist/tools/__tests__/start_ingest_job.test.js.map +1 -0
- package/dist/tools/__tests__/test_gap_intelligence.test.d.ts +2 -0
- package/dist/tools/__tests__/test_gap_intelligence.test.d.ts.map +1 -0
- package/dist/tools/__tests__/test_gap_intelligence.test.js +77 -0
- package/dist/tools/__tests__/test_gap_intelligence.test.js.map +1 -0
- package/dist/tools/__tests__/trace.test.d.ts +2 -0
- package/dist/tools/__tests__/trace.test.d.ts.map +1 -0
- package/dist/tools/__tests__/trace.test.js +130 -0
- package/dist/tools/__tests__/trace.test.js.map +1 -0
- package/dist/tools/__tests__/what_broke.test.d.ts +2 -0
- package/dist/tools/__tests__/what_broke.test.d.ts.map +1 -0
- package/dist/tools/__tests__/what_broke.test.js +60 -0
- package/dist/tools/__tests__/what_broke.test.js.map +1 -0
- package/dist/tools/__tests__/wip.test.d.ts +2 -0
- package/dist/tools/__tests__/wip.test.d.ts.map +1 -0
- package/dist/tools/__tests__/wip.test.js +173 -0
- package/dist/tools/__tests__/wip.test.js.map +1 -0
- package/dist/tools/_define.d.ts +11 -0
- package/dist/tools/_define.d.ts.map +1 -0
- package/dist/tools/_define.js +29 -0
- package/dist/tools/_define.js.map +1 -0
- package/dist/tools/_job-store.d.ts +19 -0
- package/dist/tools/_job-store.d.ts.map +1 -0
- package/dist/tools/_job-store.js +26 -0
- package/dist/tools/_job-store.js.map +1 -0
- package/dist/tools/_project-root.d.ts +20 -0
- package/dist/tools/_project-root.d.ts.map +1 -0
- package/dist/tools/_project-root.js +44 -0
- package/dist/tools/_project-root.js.map +1 -0
- package/dist/tools/analyze_field.d.ts +2 -0
- package/dist/tools/analyze_field.d.ts.map +1 -0
- package/dist/tools/analyze_field.js +77 -0
- package/dist/tools/analyze_field.js.map +1 -0
- package/dist/tools/cross_layer_flow_map.d.ts +2 -0
- package/dist/tools/cross_layer_flow_map.d.ts.map +1 -0
- package/dist/tools/cross_layer_flow_map.js +104 -0
- package/dist/tools/cross_layer_flow_map.js.map +1 -0
- package/dist/tools/cross_org_diff.d.ts +2 -0
- package/dist/tools/cross_org_diff.d.ts.map +1 -0
- package/dist/tools/cross_org_diff.js +59 -0
- package/dist/tools/cross_org_diff.js.map +1 -0
- package/dist/tools/dead_code_audit.d.ts +2 -0
- package/dist/tools/dead_code_audit.d.ts.map +1 -0
- package/dist/tools/dead_code_audit.js +67 -0
- package/dist/tools/dead_code_audit.js.map +1 -0
- package/dist/tools/deployment_manifest_gen.d.ts +2 -0
- package/dist/tools/deployment_manifest_gen.d.ts.map +1 -0
- package/dist/tools/deployment_manifest_gen.js +43 -0
- package/dist/tools/deployment_manifest_gen.js.map +1 -0
- package/dist/tools/explain_code.d.ts +2 -0
- package/dist/tools/explain_code.d.ts.map +1 -0
- package/dist/tools/explain_code.js +109 -0
- package/dist/tools/explain_code.js.map +1 -0
- package/dist/tools/freshness_report.d.ts +2 -0
- package/dist/tools/freshness_report.d.ts.map +1 -0
- package/dist/tools/freshness_report.js +66 -0
- package/dist/tools/freshness_report.js.map +1 -0
- package/dist/tools/get_ingest_job.d.ts +2 -0
- package/dist/tools/get_ingest_job.d.ts.map +1 -0
- package/dist/tools/get_ingest_job.js +24 -0
- package/dist/tools/get_ingest_job.js.map +1 -0
- package/dist/tools/governor_risk_check.d.ts +2 -0
- package/dist/tools/governor_risk_check.d.ts.map +1 -0
- package/dist/tools/governor_risk_check.js +50 -0
- package/dist/tools/governor_risk_check.js.map +1 -0
- package/dist/tools/impact_from_git_diff.d.ts +2 -0
- package/dist/tools/impact_from_git_diff.d.ts.map +1 -0
- package/dist/tools/impact_from_git_diff.js +67 -0
- package/dist/tools/impact_from_git_diff.js.map +1 -0
- package/dist/tools/index.d.ts +27 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +28 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list_orgs.d.ts +30 -0
- package/dist/tools/list_orgs.d.ts.map +1 -0
- package/dist/tools/list_orgs.js +302 -0
- package/dist/tools/list_orgs.js.map +1 -0
- package/dist/tools/ping.d.ts +3 -0
- package/dist/tools/ping.d.ts.map +1 -0
- package/dist/tools/ping.js +23 -0
- package/dist/tools/ping.js.map +1 -0
- package/dist/tools/point_in_time_diff.d.ts +2 -0
- package/dist/tools/point_in_time_diff.d.ts.map +1 -0
- package/dist/tools/point_in_time_diff.js +37 -0
- package/dist/tools/point_in_time_diff.js.map +1 -0
- package/dist/tools/security_audit.d.ts +2 -0
- package/dist/tools/security_audit.d.ts.map +1 -0
- package/dist/tools/security_audit.js +56 -0
- package/dist/tools/security_audit.js.map +1 -0
- package/dist/tools/snapshot_create.d.ts +2 -0
- package/dist/tools/snapshot_create.d.ts.map +1 -0
- package/dist/tools/snapshot_create.js +24 -0
- package/dist/tools/snapshot_create.js.map +1 -0
- package/dist/tools/snapshot_list.d.ts +2 -0
- package/dist/tools/snapshot_list.d.ts.map +1 -0
- package/dist/tools/snapshot_list.js +22 -0
- package/dist/tools/snapshot_list.js.map +1 -0
- package/dist/tools/staleness_check.d.ts +2 -0
- package/dist/tools/staleness_check.d.ts.map +1 -0
- package/dist/tools/staleness_check.js +50 -0
- package/dist/tools/staleness_check.js.map +1 -0
- package/dist/tools/start_ingest_job.d.ts +2 -0
- package/dist/tools/start_ingest_job.d.ts.map +1 -0
- package/dist/tools/start_ingest_job.js +83 -0
- package/dist/tools/start_ingest_job.js.map +1 -0
- package/dist/tools/test_gap_intelligence_from_git_diff.d.ts +2 -0
- package/dist/tools/test_gap_intelligence_from_git_diff.d.ts.map +1 -0
- package/dist/tools/test_gap_intelligence_from_git_diff.js +50 -0
- package/dist/tools/test_gap_intelligence_from_git_diff.js.map +1 -0
- package/dist/tools/trace_downstream.d.ts +2 -0
- package/dist/tools/trace_downstream.d.ts.map +1 -0
- package/dist/tools/trace_downstream.js +43 -0
- package/dist/tools/trace_downstream.js.map +1 -0
- package/dist/tools/trace_upstream.d.ts +2 -0
- package/dist/tools/trace_upstream.d.ts.map +1 -0
- package/dist/tools/trace_upstream.js +43 -0
- package/dist/tools/trace_upstream.js.map +1 -0
- package/dist/tools/what_broke.d.ts +2 -0
- package/dist/tools/what_broke.d.ts.map +1 -0
- package/dist/tools/what_broke.js +86 -0
- package/dist/tools/what_broke.js.map +1 -0
- package/dist/tools/wip_diff.d.ts +2 -0
- package/dist/tools/wip_diff.d.ts.map +1 -0
- package/dist/tools/wip_diff.js +55 -0
- package/dist/tools/wip_diff.js.map +1 -0
- package/dist/tools/wip_impact.d.ts +2 -0
- package/dist/tools/wip_impact.d.ts.map +1 -0
- package/dist/tools/wip_impact.js +55 -0
- package/dist/tools/wip_impact.js.map +1 -0
- package/dist/tools/wip_test_gap.d.ts +2 -0
- package/dist/tools/wip_test_gap.d.ts.map +1 -0
- package/dist/tools/wip_test_gap.js +50 -0
- package/dist/tools/wip_test_gap.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { loadBetterSqlite3 } from "@ryanstark24/sfgraph-core";
|
|
5
|
+
import { getSfgraphPaths, validateOrgIdentifier } from "@ryanstark24/sfgraph-shared";
|
|
6
|
+
const nodeRequire = createRequire(import.meta.url);
|
|
7
|
+
import { defineTool, z } from "./_define.js";
|
|
8
|
+
const inputSchema = z.object({}).strict();
|
|
9
|
+
const DAY_MS = 1000 * 60 * 60 * 24;
|
|
10
|
+
const STALE_THRESHOLD_DAYS = 7;
|
|
11
|
+
let depsOverride = null;
|
|
12
|
+
/** Test seam — replace the SF core loader / DB opener / paths. */
|
|
13
|
+
export function __setListOrgsDeps(d) {
|
|
14
|
+
depsOverride = d;
|
|
15
|
+
}
|
|
16
|
+
/** Read the alias map + authorizations from the install-time snapshot if it
|
|
17
|
+
* exists. The snapshot is written by `sfgraph install` running OUTSIDE the
|
|
18
|
+
* sandbox, then read by the sandboxed MCP child here. This is the only
|
|
19
|
+
* reliable alias source when Cursor's sandbox blocks ~/.sf/alias.json. */
|
|
20
|
+
function readSnapshot(dataDir) {
|
|
21
|
+
try {
|
|
22
|
+
const p = path.join(dataDir, "orgs-snapshot.json");
|
|
23
|
+
if (!existsSync(p))
|
|
24
|
+
return null;
|
|
25
|
+
const { readFileSync } = nodeRequire("node:fs");
|
|
26
|
+
const raw = JSON.parse(readFileSync(p, "utf8"));
|
|
27
|
+
const aliasByUsername = new Map();
|
|
28
|
+
for (const [alias, username] of Object.entries(raw.aliases ?? {})) {
|
|
29
|
+
if (typeof username === "string")
|
|
30
|
+
aliasByUsername.set(username, alias);
|
|
31
|
+
}
|
|
32
|
+
const authorizations = Object.entries(raw.authorizations ?? {}).map(([username, info]) => ({
|
|
33
|
+
alias: aliasByUsername.get(username) ?? null,
|
|
34
|
+
username,
|
|
35
|
+
orgId: info.orgId,
|
|
36
|
+
instanceUrl: info.instanceUrl,
|
|
37
|
+
}));
|
|
38
|
+
return {
|
|
39
|
+
defaultAlias: raw.defaultAlias ?? null,
|
|
40
|
+
aliasByUsername,
|
|
41
|
+
authorizations,
|
|
42
|
+
recordedAt: typeof raw.recordedAt === "number" ? raw.recordedAt : null,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
async function defaultLoadSfCore() {
|
|
50
|
+
const modName = "@salesforce/core";
|
|
51
|
+
const sfCore = (await import(modName));
|
|
52
|
+
const aliasByUsername = new Map();
|
|
53
|
+
if (sfCore.StateAggregator?.create) {
|
|
54
|
+
try {
|
|
55
|
+
const agg = await sfCore.StateAggregator.create();
|
|
56
|
+
const all = agg.aliases.getAll();
|
|
57
|
+
for (const [alias, username] of Object.entries(all)) {
|
|
58
|
+
if (typeof username === "string" && username.length > 0) {
|
|
59
|
+
aliasByUsername.set(username, alias);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// StateAggregator failed; alias enumeration just stays empty.
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return { AuthInfo: sfCore.AuthInfo, aliasByUsername };
|
|
68
|
+
}
|
|
69
|
+
async function defaultResolveDefault() {
|
|
70
|
+
try {
|
|
71
|
+
const mod = (await import("@ryanstark24/sfgraph-core"));
|
|
72
|
+
if (typeof mod.resolveDefaultOrgAlias === "function") {
|
|
73
|
+
return await mod.resolveDefaultOrgAlias();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// ignore
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
/** Diagnostic counter — captured into the summary so silent open failures
|
|
82
|
+
* (missing native binding, wrong arch, etc.) don't hide behind '0 orgs'. */
|
|
83
|
+
let lastOpenDbError = null;
|
|
84
|
+
function defaultOpenDb(p) {
|
|
85
|
+
if (!existsSync(p))
|
|
86
|
+
return null;
|
|
87
|
+
try {
|
|
88
|
+
const Database = loadBetterSqlite3(nodeRequire);
|
|
89
|
+
const db = new Database(p, { readonly: true, fileMustExist: true });
|
|
90
|
+
return db;
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
lastOpenDbError = e.message;
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
defineTool({
|
|
98
|
+
name: "list_orgs",
|
|
99
|
+
description: "USE THIS as the FIRST step in any sfgraph workflow to enumerate the user's available Salesforce orgs and their ingest status. Shows aliases, orgIds, default-org marker, ingested-locally flag, last-synced timestamp, stale flag. Works even when the sf CLI auth isn't reachable from this process (falls back to scanning the local data dir).",
|
|
100
|
+
inputSchema,
|
|
101
|
+
async execute(_input) {
|
|
102
|
+
const deps = depsOverride ?? {};
|
|
103
|
+
const loadSfCore = deps.loadSfCore ?? defaultLoadSfCore;
|
|
104
|
+
const resolveDefault = deps.resolveDefaultOrgAlias ?? defaultResolveDefault;
|
|
105
|
+
const dataDir = deps.dataDir ?? getSfgraphPaths().data;
|
|
106
|
+
const openDb = deps.openDb ?? defaultOpenDb;
|
|
107
|
+
let auths = [];
|
|
108
|
+
let aliasByUsername = new Map();
|
|
109
|
+
let loadError = null;
|
|
110
|
+
try {
|
|
111
|
+
const sfCore = await loadSfCore();
|
|
112
|
+
auths = await sfCore.AuthInfo.listAllAuthorizations();
|
|
113
|
+
if (sfCore.aliasByUsername)
|
|
114
|
+
aliasByUsername = sfCore.aliasByUsername;
|
|
115
|
+
}
|
|
116
|
+
catch (e) {
|
|
117
|
+
loadError = e.message;
|
|
118
|
+
}
|
|
119
|
+
let defaultAlias = null;
|
|
120
|
+
try {
|
|
121
|
+
defaultAlias = await resolveDefault();
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
defaultAlias = null;
|
|
125
|
+
}
|
|
126
|
+
// Sandbox fallback: when the MCP child can't read ~/.sf/ directly
|
|
127
|
+
// (Cursor's macOS sandbox), AuthInfo/StateAggregator/ConfigAggregator
|
|
128
|
+
// all come back empty. `sfgraph install` runs OUTSIDE the sandbox and
|
|
129
|
+
// snapshots that state to <dataDir>/orgs-snapshot.json. Merge it in
|
|
130
|
+
// here as the authoritative source when the live calls returned
|
|
131
|
+
// nothing useful.
|
|
132
|
+
const snap = readSnapshot(dataDir);
|
|
133
|
+
if (snap) {
|
|
134
|
+
if (auths.length === 0)
|
|
135
|
+
auths = snap.authorizations;
|
|
136
|
+
if (aliasByUsername.size === 0)
|
|
137
|
+
aliasByUsername = snap.aliasByUsername;
|
|
138
|
+
if (!defaultAlias && snap.defaultAlias)
|
|
139
|
+
defaultAlias = snap.defaultAlias;
|
|
140
|
+
}
|
|
141
|
+
const now = Date.now();
|
|
142
|
+
const byOrgId = new Map();
|
|
143
|
+
// Pass 1 — orgs visible via @salesforce/core (the sf CLI auth dir).
|
|
144
|
+
// When the MCP server runs as a child process of Cursor / Claude with
|
|
145
|
+
// no shell env, this call sometimes returns empty even though the user
|
|
146
|
+
// is authenticated in their shell. Pass 2 below catches that case by
|
|
147
|
+
// scanning the local data dir for ingested orgs.
|
|
148
|
+
for (const a of auths) {
|
|
149
|
+
const username = a.username ?? "";
|
|
150
|
+
// Prefer the alias on the AuthorizationRow; if absent, fall back to
|
|
151
|
+
// the username -> alias map from StateAggregator. This is the actual
|
|
152
|
+
// fix for 'all aliases show _none_': AuthInfo.listAllAuthorizations
|
|
153
|
+
// routinely returns alias=null even when `sf org list` shows one.
|
|
154
|
+
const alias = (a.alias ?? null) || aliasByUsername.get(username) || null;
|
|
155
|
+
const orgId = a.orgId ?? "";
|
|
156
|
+
const instanceUrl = a.instanceUrl ?? "";
|
|
157
|
+
const isDefault = !!defaultAlias && (defaultAlias === alias || defaultAlias === username);
|
|
158
|
+
if (!orgId)
|
|
159
|
+
continue;
|
|
160
|
+
// Try to open this org's local DB to read last-synced timestamp.
|
|
161
|
+
let lastSyncedAt = null;
|
|
162
|
+
let ingested = false;
|
|
163
|
+
const dbPath = path.join(dataDir, `${orgId}.sqlite`);
|
|
164
|
+
const db = openDb(dbPath);
|
|
165
|
+
if (db) {
|
|
166
|
+
ingested = true;
|
|
167
|
+
try {
|
|
168
|
+
const row = db
|
|
169
|
+
.prepare("SELECT last_synced_at FROM _sfgraph_orgs WHERE id = ?")
|
|
170
|
+
.get(orgId);
|
|
171
|
+
if (row && row.last_synced_at != null) {
|
|
172
|
+
lastSyncedAt = Number(row.last_synced_at);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
// table missing or schema older than v4
|
|
177
|
+
}
|
|
178
|
+
try {
|
|
179
|
+
db.close();
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
// ignore
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
byOrgId.set(orgId, {
|
|
186
|
+
alias,
|
|
187
|
+
username,
|
|
188
|
+
orgId,
|
|
189
|
+
instanceUrl,
|
|
190
|
+
isDefault,
|
|
191
|
+
ingested,
|
|
192
|
+
lastSyncedAt,
|
|
193
|
+
ageDays: null,
|
|
194
|
+
stale: true,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
// Pass 2 — orgs visible via the local data dir. ANY <orgId>.sqlite that
|
|
198
|
+
// contains an _sfgraph_orgs row is a valid usable graph regardless of
|
|
199
|
+
// whether the sf CLI auth is currently accessible to this process.
|
|
200
|
+
if (existsSync(dataDir)) {
|
|
201
|
+
let files = [];
|
|
202
|
+
try {
|
|
203
|
+
files = readdirSync(dataDir).filter((f) => f.endsWith(".sqlite") && !f.startsWith("backups"));
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
files = [];
|
|
207
|
+
}
|
|
208
|
+
for (const f of files) {
|
|
209
|
+
const orgId = f.replace(/\.sqlite$/, "");
|
|
210
|
+
if (!orgId || orgId.includes("/"))
|
|
211
|
+
continue;
|
|
212
|
+
// Harden: skip any file whose stem isn't a valid org identifier.
|
|
213
|
+
try {
|
|
214
|
+
validateOrgIdentifier(orgId);
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
const dbPath = path.join(dataDir, f);
|
|
220
|
+
const db = openDb(dbPath);
|
|
221
|
+
if (!db)
|
|
222
|
+
continue;
|
|
223
|
+
let storedAlias = null;
|
|
224
|
+
let storedInstance = null;
|
|
225
|
+
let lastSyncedAt = null;
|
|
226
|
+
try {
|
|
227
|
+
const row = db
|
|
228
|
+
.prepare("SELECT alias, instance_url, last_synced_at FROM _sfgraph_orgs WHERE id = ?")
|
|
229
|
+
.get(orgId);
|
|
230
|
+
if (row) {
|
|
231
|
+
storedAlias = row.alias ?? null;
|
|
232
|
+
storedInstance = row.instance_url ?? null;
|
|
233
|
+
if (row.last_synced_at != null)
|
|
234
|
+
lastSyncedAt = Number(row.last_synced_at);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch {
|
|
238
|
+
// table missing or schema older than v4
|
|
239
|
+
}
|
|
240
|
+
try {
|
|
241
|
+
db.close();
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
// ignore
|
|
245
|
+
}
|
|
246
|
+
const existing = byOrgId.get(orgId);
|
|
247
|
+
if (existing) {
|
|
248
|
+
existing.ingested = true;
|
|
249
|
+
if (lastSyncedAt != null)
|
|
250
|
+
existing.lastSyncedAt = lastSyncedAt;
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
byOrgId.set(orgId, {
|
|
254
|
+
alias: storedAlias,
|
|
255
|
+
username: "",
|
|
256
|
+
orgId,
|
|
257
|
+
instanceUrl: storedInstance ?? "",
|
|
258
|
+
isDefault: !!defaultAlias && !!storedAlias && defaultAlias === storedAlias,
|
|
259
|
+
ingested: true,
|
|
260
|
+
lastSyncedAt,
|
|
261
|
+
ageDays: null,
|
|
262
|
+
stale: true,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
const orgs = [...byOrgId.values()].map((o) => {
|
|
268
|
+
const ageDays = o.lastSyncedAt != null ? Math.floor((now - o.lastSyncedAt) / DAY_MS) : null;
|
|
269
|
+
const stale = ageDays == null ? true : ageDays >= STALE_THRESHOLD_DAYS;
|
|
270
|
+
return { ...o, ageDays, stale };
|
|
271
|
+
});
|
|
272
|
+
const rows = orgs
|
|
273
|
+
.map((o) => `| ${o.alias ?? "_none_"} | \`${o.orgId || "_unknown_"}\` | ${o.isDefault ? "yes" : ""} | ${o.ingested ? "yes" : "no"} | ${o.lastSyncedAt != null ? new Date(o.lastSyncedAt).toISOString() : "_never_"} | ${o.stale ? "yes" : "no"} |`)
|
|
274
|
+
.join("\n");
|
|
275
|
+
const header = "| Alias | Org Id | Default | Ingested | Last Synced | Stale |\n|---|---|---|---|---|---|";
|
|
276
|
+
const md = orgs.length === 0 ? "_no orgs_" : `${header}\n${rows}`;
|
|
277
|
+
const authCount = auths.length;
|
|
278
|
+
const ingestedCount = orgs.filter((o) => o.ingested).length;
|
|
279
|
+
const dbErrSuffix = lastOpenDbError ? ` [openDb error: ${lastOpenDbError}]` : "";
|
|
280
|
+
// Surface snapshot age. If the install-time snapshot is older than 7
|
|
281
|
+
// days, the user has likely changed sf state (logged into a new org,
|
|
282
|
+
// re-aliased, flipped target-org) and the in-MCP list is stale.
|
|
283
|
+
let snapshotSuffix = "";
|
|
284
|
+
if (snap?.recordedAt) {
|
|
285
|
+
const ageDays = Math.floor((now - snap.recordedAt) / DAY_MS);
|
|
286
|
+
if (ageDays >= STALE_THRESHOLD_DAYS) {
|
|
287
|
+
snapshotSuffix = ` ⚠ org snapshot is ${ageDays} days old — run \`sfgraph refresh-orgs\` to pick up any sf-CLI changes`;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const summary = loadError
|
|
291
|
+
? `sf-cli auth unavailable in this process (${loadError}); discovered ${orgs.length} org${orgs.length === 1 ? "" : "s"} from local sfgraph data dir (${ingestedCount} ingested)${dbErrSuffix}${snapshotSuffix}`
|
|
292
|
+
: `${orgs.length} org${orgs.length === 1 ? "" : "s"} total — ${authCount} via sf CLI, ${ingestedCount} ingested locally${dbErrSuffix}${snapshotSuffix}`;
|
|
293
|
+
// Reset for next invocation so a transient error doesn't stick.
|
|
294
|
+
lastOpenDbError = null;
|
|
295
|
+
return {
|
|
296
|
+
summary,
|
|
297
|
+
markdown: md,
|
|
298
|
+
data: { orgs, defaultAlias },
|
|
299
|
+
};
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
//# sourceMappingURL=list_orgs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list_orgs.js","sourceRoot":"","sources":["../../src/tools/list_orgs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ping.d.ts","sourceRoot":"","sources":["../../src/tools/ping.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAiB1D,eAAO,MAAM,QAAQ,EAAE,cAOtB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { defineTool, z } from "./_define.js";
|
|
2
|
+
defineTool({
|
|
3
|
+
name: "ping",
|
|
4
|
+
description: "health check — returns ok+ts",
|
|
5
|
+
inputSchema: z.object({}).strict(),
|
|
6
|
+
async execute() {
|
|
7
|
+
return {
|
|
8
|
+
summary: "ok",
|
|
9
|
+
markdown: "pong",
|
|
10
|
+
data: { ok: true, ts: Date.now() },
|
|
11
|
+
};
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
// Back-compat export for Phase 0 tests that import pingTool directly.
|
|
15
|
+
export const pingTool = {
|
|
16
|
+
name: "ping",
|
|
17
|
+
schema: {
|
|
18
|
+
description: "health check",
|
|
19
|
+
inputSchema: { type: "object", properties: {} },
|
|
20
|
+
},
|
|
21
|
+
handler: async () => ({ ok: true, ts: Date.now() }),
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=ping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ping.js","sourceRoot":"","sources":["../../src/tools/ping.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAE7C,UAAU,CAAC;IACT,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,8BAA8B;IAC3C,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;IAClC,KAAK,CAAC,OAAO;QACX,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,MAAM;YAChB,IAAI,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE;SACnC,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,sEAAsE;AACtE,MAAM,CAAC,MAAM,QAAQ,GAAmB;IACtC,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE;QACN,WAAW,EAAE,cAAc;QAC3B,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,EAAE;KAChD;IACD,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;CACpD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"point_in_time_diff.d.ts","sourceRoot":"","sources":["../../src/tools/point_in_time_diff.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { render } from "@ryanstark24/sfgraph-core";
|
|
2
|
+
import { getToolContext } from "../context.js";
|
|
3
|
+
import { defineTool, z } from "./_define.js";
|
|
4
|
+
const inputSchema = z.object({
|
|
5
|
+
org: z.string().min(1),
|
|
6
|
+
from: z.string().min(1),
|
|
7
|
+
to: z.union([z.string().min(1), z.literal("current")]).default("current"),
|
|
8
|
+
});
|
|
9
|
+
defineTool({
|
|
10
|
+
name: "point_in_time_diff",
|
|
11
|
+
description: "Diff org graph between two snapshots (or snapshot vs current).",
|
|
12
|
+
inputSchema,
|
|
13
|
+
async execute(input) {
|
|
14
|
+
const ctx = await getToolContext({ orgId: input.org });
|
|
15
|
+
const nodeDiff = ctx.snapshotStore.diffNodes(ctx.orgId, input.from, input.to);
|
|
16
|
+
const edgeDiff = ctx.snapshotStore.diffEdges(ctx.orgId, input.from, input.to);
|
|
17
|
+
const mermaid = render.renderDiff({
|
|
18
|
+
added: nodeDiff.added.map((n) => ({ qualifiedName: n.qualifiedName })),
|
|
19
|
+
removed: nodeDiff.removed.map((n) => ({ qualifiedName: n.qualifiedName })),
|
|
20
|
+
changed: nodeDiff.changed.map((c) => ({ qualifiedName: c.after.qualifiedName })),
|
|
21
|
+
});
|
|
22
|
+
const md = [
|
|
23
|
+
`**Nodes** — +${nodeDiff.added.length} / -${nodeDiff.removed.length} / ~${nodeDiff.changed.length}`,
|
|
24
|
+
`**Edges** — +${edgeDiff.added.length} / -${edgeDiff.removed.length}`,
|
|
25
|
+
"",
|
|
26
|
+
"```mermaid",
|
|
27
|
+
mermaid,
|
|
28
|
+
"```",
|
|
29
|
+
].join("\n");
|
|
30
|
+
return {
|
|
31
|
+
summary: `diff: +${nodeDiff.added.length} ~${nodeDiff.changed.length} -${nodeDiff.removed.length}`,
|
|
32
|
+
markdown: md,
|
|
33
|
+
data: { nodeDiff, edgeDiff },
|
|
34
|
+
};
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=point_in_time_diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"point_in_time_diff.js","sourceRoot":"","sources":["../../src/tools/point_in_time_diff.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC;CAC1E,CAAC,CAAC;AAEH,UAAU,CAAC;IACT,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EAAE,gEAAgE;IAC7E,WAAW;IACX,KAAK,CAAC,OAAO,CAAC,KAAK;QACjB,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QACvD,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9E,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9E,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC;YAChC,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;YACtE,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC;YAC1E,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC,CAAC;SACjF,CAAC,CAAC;QACH,MAAM,EAAE,GAAG;YACT,gBAAgB,QAAQ,CAAC,KAAK,CAAC,MAAM,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE;YACnG,gBAAgB,QAAQ,CAAC,KAAK,CAAC,MAAM,OAAO,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE;YACrE,EAAE;YACF,YAAY;YACZ,OAAO;YACP,KAAK;SACN,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,OAAO;YACL,OAAO,EAAE,UAAU,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,OAAO,CAAC,MAAM,KAAK,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE;YAClG,QAAQ,EAAE,EAAE;YACZ,IAAI,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;SAC7B,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security_audit.d.ts","sourceRoot":"","sources":["../../src/tools/security_audit.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { analyze } from "@ryanstark24/sfgraph-core";
|
|
2
|
+
import { getToolContext } from "../context.js";
|
|
3
|
+
import { defineTool, z } from "./_define.js";
|
|
4
|
+
const inputSchema = z.object({
|
|
5
|
+
org: z.string().min(1),
|
|
6
|
+
/** Narrow the audit to a single SObject. Accepts `Account` or `CustomObject:Account`. */
|
|
7
|
+
object: z.string().min(1).optional(),
|
|
8
|
+
/** Narrow the audit to a single field. Accepts a full qname like `CustomField:Account.Tier__c`. */
|
|
9
|
+
field: z.string().min(1).optional(),
|
|
10
|
+
});
|
|
11
|
+
defineTool({
|
|
12
|
+
name: "security_audit",
|
|
13
|
+
description: "USE THIS for any 'FLS' / 'who has access to X' / 'security audit' / 'sharing rules' / 'permission audit' question about a Salesforce org. Returns full-access sharing rules, FLS gaps on PII-shaped fields, and the Profile/PermSet -> Object/Field access matrix. Optional `object` / `field` filters narrow the FLS-gap + access-matrix output to a single SObject or field.",
|
|
14
|
+
inputSchema,
|
|
15
|
+
async execute(input) {
|
|
16
|
+
const ctx = await getToolContext({ orgId: input.org });
|
|
17
|
+
const filter = {};
|
|
18
|
+
if (input.object !== undefined)
|
|
19
|
+
filter.object = input.object;
|
|
20
|
+
if (input.field !== undefined)
|
|
21
|
+
filter.field = input.field;
|
|
22
|
+
const audit = analyze.securityAudit(ctx.graphStore, ctx.orgId, filter);
|
|
23
|
+
// Augment with cached findings table if present
|
|
24
|
+
let cachedFindings = [];
|
|
25
|
+
if (ctx.db) {
|
|
26
|
+
try {
|
|
27
|
+
const d = ctx.db;
|
|
28
|
+
cachedFindings = d
|
|
29
|
+
.prepare("SELECT qualified_name, rule_id, message FROM _sfgraph_findings WHERE org_id = ? ORDER BY rule_id")
|
|
30
|
+
.all(ctx.orgId)
|
|
31
|
+
.map((r) => ({ qname: r.qualified_name, rule: r.rule_id, message: r.message }));
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
/* table may not exist */
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const md = [
|
|
38
|
+
`**Full-access sharing rules:** ${audit.sharingFullAccess.length}`,
|
|
39
|
+
...audit.sharingFullAccess.slice(0, 20).map((q) => `- \`${q}\``),
|
|
40
|
+
"",
|
|
41
|
+
`**FLS gaps (fields with no permission-set grant):** ${audit.flsGaps.length}`,
|
|
42
|
+
...audit.flsGaps.slice(0, 20).map((q) => `- \`${q}\``),
|
|
43
|
+
].join("\n");
|
|
44
|
+
const truncationNote = audit.truncated
|
|
45
|
+
? ` — results capped at ${analyze.SECURITY_PER_LABEL_CAP}/label; narrow with object/field`
|
|
46
|
+
: "";
|
|
47
|
+
return {
|
|
48
|
+
summary: `${audit.flsGaps.length} FLS gaps, ${audit.sharingFullAccess.length} full-access rules${truncationNote}`,
|
|
49
|
+
markdown: audit.truncated
|
|
50
|
+
? `${md}\n\n> _Note: at least one label hit the ${analyze.SECURITY_PER_LABEL_CAP}-row cap. Results are incomplete — pass \`object\` or \`field\` to narrow._`
|
|
51
|
+
: md,
|
|
52
|
+
data: { ...audit, cachedFindings, truncated: audit.truncated ?? false },
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
//# sourceMappingURL=security_audit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"security_audit.js","sourceRoot":"","sources":["../../src/tools/security_audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,yFAAyF;IACzF,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;IACpC,mGAAmG;IACnG,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE;CACpC,CAAC,CAAC;AAEH,UAAU,CAAC;IACT,IAAI,EAAE,gBAAgB;IACtB,WAAW,EACT,gXAAgX;IAClX,WAAW;IACX,KAAK,CAAC,OAAO,CAAC,KAAK;QACjB,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QACvD,MAAM,MAAM,GAAwC,EAAE,CAAC;QACvD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;YAAE,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;QAC7D,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,UAAU,EAAE,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACvE,gDAAgD;QAChD,IAAI,cAAc,GAA4D,EAAE,CAAC;QACjF,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;YACX,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,GAAG,CAAC,EAMb,CAAC;gBACF,cAAc,GAAG,CAAC;qBACf,OAAO,CACN,kGAAkG,CACnG;qBACA,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC;qBACd,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACpF,CAAC;YAAC,MAAM,CAAC;gBACP,yBAAyB;YAC3B,CAAC;QACH,CAAC;QACD,MAAM,EAAE,GAAG;YACT,kCAAkC,KAAK,CAAC,iBAAiB,CAAC,MAAM,EAAE;YAClE,GAAG,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;YAChE,EAAE;YACF,uDAAuD,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE;YAC7E,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;SACvD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,MAAM,cAAc,GAAG,KAAK,CAAC,SAAS;YACpC,CAAC,CAAC,wBAAwB,OAAO,CAAC,sBAAsB,kCAAkC;YAC1F,CAAC,CAAC,EAAE,CAAC;QACP,OAAO;YACL,OAAO,EAAE,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,cAAc,KAAK,CAAC,iBAAiB,CAAC,MAAM,qBAAqB,cAAc,EAAE;YACjH,QAAQ,EAAE,KAAK,CAAC,SAAS;gBACvB,CAAC,CAAC,GAAG,EAAE,2CAA2C,OAAO,CAAC,sBAAsB,6EAA6E;gBAC7J,CAAC,CAAC,EAAE;YACN,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,KAAK,EAAE;SACxE,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot_create.d.ts","sourceRoot":"","sources":["../../src/tools/snapshot_create.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { getToolContext } from "../context.js";
|
|
2
|
+
import { defineTool, z } from "./_define.js";
|
|
3
|
+
const inputSchema = z.object({
|
|
4
|
+
org: z.string().min(1),
|
|
5
|
+
name: z.string().optional(),
|
|
6
|
+
kind: z.enum(["manual", "scheduled"]).default("manual"),
|
|
7
|
+
});
|
|
8
|
+
defineTool({
|
|
9
|
+
name: "snapshot_create",
|
|
10
|
+
description: "Create a graph snapshot for an org.",
|
|
11
|
+
inputSchema,
|
|
12
|
+
async execute(input) {
|
|
13
|
+
const ctx = await getToolContext({ orgId: input.org });
|
|
14
|
+
const label = input.name ?? `${input.kind}-${new Date().toISOString()}`;
|
|
15
|
+
const snap = ctx.snapshotStore.createSnapshot(ctx.orgId, label, false);
|
|
16
|
+
return {
|
|
17
|
+
summary: `snapshot ${snap.id} created`,
|
|
18
|
+
markdown: `Snapshot \`${snap.id}\` (\"${label}\") created for org \`${ctx.orgId}\`.`,
|
|
19
|
+
data: snap,
|
|
20
|
+
follow_up_tools: ["snapshot_list", "point_in_time_diff"],
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
});
|
|
24
|
+
//# sourceMappingURL=snapshot_create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot_create.js","sourceRoot":"","sources":["../../src/tools/snapshot_create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3B,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACtB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC;CACxD,CAAC,CAAC;AAEH,UAAU,CAAC;IACT,IAAI,EAAE,iBAAiB;IACvB,WAAW,EAAE,qCAAqC;IAClD,WAAW;IACX,KAAK,CAAC,OAAO,CAAC,KAAK;QACjB,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QACvD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,IAAI,GAAG,KAAK,CAAC,IAAI,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;QACxE,MAAM,IAAI,GAAG,GAAG,CAAC,aAAa,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QACvE,OAAO;YACL,OAAO,EAAE,YAAY,IAAI,CAAC,EAAE,UAAU;YACtC,QAAQ,EAAE,cAAc,IAAI,CAAC,EAAE,SAAS,KAAK,yBAAyB,GAAG,CAAC,KAAK,KAAK;YACpF,IAAI,EAAE,IAAI;YACV,eAAe,EAAE,CAAC,eAAe,EAAE,oBAAoB,CAAC;SACzD,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot_list.d.ts","sourceRoot":"","sources":["../../src/tools/snapshot_list.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { getToolContext } from "../context.js";
|
|
2
|
+
import { defineTool, z } from "./_define.js";
|
|
3
|
+
const inputSchema = z.object({ org: z.string().min(1) });
|
|
4
|
+
defineTool({
|
|
5
|
+
name: "snapshot_list",
|
|
6
|
+
description: "List up to 20 most recent snapshots for an org.",
|
|
7
|
+
inputSchema,
|
|
8
|
+
async execute(input) {
|
|
9
|
+
const ctx = await getToolContext({ orgId: input.org });
|
|
10
|
+
const snaps = ctx.snapshotStore.listSnapshots(ctx.orgId).slice(0, 20);
|
|
11
|
+
const rows = snaps
|
|
12
|
+
.map((s) => `| \`${s.id}\` | ${s.label} | ${new Date(s.createdAt).toISOString()} | ${s.isAuto ? "auto" : "manual"} |`)
|
|
13
|
+
.join("\n");
|
|
14
|
+
const md = `| id | label | createdAt | kind |\n|---|---|---|---|\n${rows}`;
|
|
15
|
+
return {
|
|
16
|
+
summary: `${snaps.length} snapshots`,
|
|
17
|
+
markdown: snaps.length === 0 ? "_no snapshots_" : md,
|
|
18
|
+
data: snaps,
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=snapshot_list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot_list.js","sourceRoot":"","sources":["../../src/tools/snapshot_list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAEzD,UAAU,CAAC;IACT,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,iDAAiD;IAC9D,WAAW;IACX,KAAK,CAAC,OAAO,CAAC,KAAK;QACjB,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QACvD,MAAM,KAAK,GAAG,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACtE,MAAM,IAAI,GAAG,KAAK;aACf,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CACJ,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,CAC5G;aACA,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,MAAM,EAAE,GAAG,yDAAyD,IAAI,EAAE,CAAC;QAC3E,OAAO;YACL,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,YAAY;YACpC,QAAQ,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE;YACpD,IAAI,EAAE,KAAK;SACZ,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleness_check.d.ts","sourceRoot":"","sources":["../../src/tools/staleness_check.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { getToolContext } from "../context.js";
|
|
2
|
+
import { defineTool, z } from "./_define.js";
|
|
3
|
+
const inputSchema = z.object({ org: z.string().min(1) });
|
|
4
|
+
const DAY_MS = 1000 * 60 * 60 * 24;
|
|
5
|
+
const STALE_THRESHOLD_DAYS = 7;
|
|
6
|
+
defineTool({
|
|
7
|
+
name: "staleness_check",
|
|
8
|
+
description: "USE THIS for any 'is my graph fresh' / 'when was the last ingest' / 'should I re-ingest' question for a single Salesforce org. Returns days since last sync + stale flag (>=7 days) + the exact sfgraph ingest command to refresh. Call this FIRST in any workflow where staleness would change the answer.",
|
|
9
|
+
inputSchema,
|
|
10
|
+
async execute(input) {
|
|
11
|
+
const ctx = await getToolContext({ orgId: input.org });
|
|
12
|
+
let lastSyncedAt = null;
|
|
13
|
+
try {
|
|
14
|
+
const db = ctx.graphStore.db;
|
|
15
|
+
const row = db
|
|
16
|
+
.prepare("SELECT last_synced_at FROM _sfgraph_orgs WHERE id = ?")
|
|
17
|
+
.get(ctx.orgId);
|
|
18
|
+
if (row && row.last_synced_at != null) {
|
|
19
|
+
lastSyncedAt = Number(row.last_synced_at);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// table missing or no row — treat as never synced
|
|
24
|
+
}
|
|
25
|
+
const now = Date.now();
|
|
26
|
+
const ageDays = lastSyncedAt != null ? Math.floor((now - lastSyncedAt) / DAY_MS) : null;
|
|
27
|
+
const stale = ageDays == null || ageDays >= STALE_THRESHOLD_DAYS;
|
|
28
|
+
const recommendation = stale
|
|
29
|
+
? `ingest is ${ageDays == null ? "missing" : `${ageDays} days old`} — run \`sfgraph ingest --org ${input.org}\` to refresh before relying on this analysis`
|
|
30
|
+
: `ingest is ${ageDays} day${ageDays === 1 ? "" : "s"} old — fresh enough to use`;
|
|
31
|
+
const summary = stale ? `STALE: ${recommendation}` : `fresh: ${recommendation}`;
|
|
32
|
+
const md = [
|
|
33
|
+
"| org | last synced | age (days) | stale | recommendation |",
|
|
34
|
+
"|---|---|---|---|---|",
|
|
35
|
+
`| \`${input.org}\` | ${lastSyncedAt != null ? new Date(lastSyncedAt).toISOString() : "_never_"} | ${ageDays ?? "-"} | ${stale ? "yes" : "no"} | ${recommendation} |`,
|
|
36
|
+
].join("\n");
|
|
37
|
+
return {
|
|
38
|
+
summary,
|
|
39
|
+
markdown: md,
|
|
40
|
+
data: {
|
|
41
|
+
org: input.org,
|
|
42
|
+
lastSyncedAt,
|
|
43
|
+
ageDays,
|
|
44
|
+
stale,
|
|
45
|
+
recommendation,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=staleness_check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleness_check.js","sourceRoot":"","sources":["../../src/tools/staleness_check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAEzD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AACnC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAE/B,UAAU,CAAC;IACT,IAAI,EAAE,iBAAiB;IACvB,WAAW,EACT,6SAA6S;IAC/S,WAAW;IACX,KAAK,CAAC,OAAO,CAAC,KAAK;QACjB,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;QACvD,IAAI,YAAY,GAAkB,IAAI,CAAC;QACvC,IAAI,CAAC;YACH,MAAM,EAAE,GACN,GAAG,CAAC,UAGL,CAAC,EAAE,CAAC;YACL,MAAM,GAAG,GAAG,EAAE;iBACX,OAAO,CAAC,uDAAuD,CAAC;iBAChE,GAAG,CAAC,GAAG,CAAC,KAAK,CAAkD,CAAC;YACnE,IAAI,GAAG,IAAI,GAAG,CAAC,cAAc,IAAI,IAAI,EAAE,CAAC;gBACtC,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,OAAO,GAAG,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,YAAY,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACxF,MAAM,KAAK,GAAG,OAAO,IAAI,IAAI,IAAI,OAAO,IAAI,oBAAoB,CAAC;QACjE,MAAM,cAAc,GAAG,KAAK;YAC1B,CAAC,CAAC,aAAa,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,WAAW,iCAAiC,KAAK,CAAC,GAAG,+CAA+C;YAC3J,CAAC,CAAC,aAAa,OAAO,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,4BAA4B,CAAC;QACpF,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,UAAU,cAAc,EAAE,CAAC,CAAC,CAAC,UAAU,cAAc,EAAE,CAAC;QAChF,MAAM,EAAE,GAAG;YACT,6DAA6D;YAC7D,uBAAuB;YACvB,OAAO,KAAK,CAAC,GAAG,QAAQ,YAAY,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS,MAAM,OAAO,IAAI,GAAG,MAAM,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,MAAM,cAAc,IAAI;SACtK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,OAAO;YACL,OAAO;YACP,QAAQ,EAAE,EAAE;YACZ,IAAI,EAAE;gBACJ,GAAG,EAAE,KAAK,CAAC,GAAG;gBACd,YAAY;gBACZ,OAAO;gBACP,KAAK;gBACL,cAAc;aACf;SACF,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start_ingest_job.d.ts","sourceRoot":"","sources":["../../src/tools/start_ingest_job.ts"],"names":[],"mappings":""}
|