@envseal/cli 0.1.6 → 0.1.7
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/commands/doctor.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, statSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { SepError } from '@envseal/protocol';
|
|
4
|
-
import { inspectDotenvGitSafety, loadManifest, projectPaths, readHookHeartbeat } from '@envseal/core';
|
|
4
|
+
import { inspectDotenvGitSafety, loadManifest, projectPaths, readHookDecisions, readHookHeartbeat } from '@envseal/core';
|
|
5
5
|
import { emit, fail } from '../output.js';
|
|
6
6
|
import { EXIT } from '../exit-codes.js';
|
|
7
7
|
import { detectHost } from '../host.js';
|
|
@@ -49,6 +49,7 @@ export async function doctor(root, json) {
|
|
|
49
49
|
const egress = manifest?.policy?.egress;
|
|
50
50
|
const inspection = inspectPrimaryHostWiring(root, host.id, { probe: true });
|
|
51
51
|
const hookLastRan = readHookHeartbeat(root);
|
|
52
|
+
const hookDecisions = readHookDecisions(root);
|
|
52
53
|
const output = {
|
|
53
54
|
projectRoot: root,
|
|
54
55
|
manifestPath,
|
|
@@ -72,6 +73,7 @@ export async function doctor(root, json) {
|
|
|
72
73
|
egressPolicy: egress ?? { mode: 'warn', allow: [] },
|
|
73
74
|
hookFailClosed,
|
|
74
75
|
hookLastRan,
|
|
76
|
+
hookDecisions,
|
|
75
77
|
missingRequiredCount: status.missingRequired.length,
|
|
76
78
|
missingRequired: status.missingRequired,
|
|
77
79
|
rotationOverdue: status.entries
|
|
@@ -85,6 +87,9 @@ export async function doctor(root, json) {
|
|
|
85
87
|
status: inspection.mcp.status,
|
|
86
88
|
message: inspection.mcp.message,
|
|
87
89
|
commandOk: inspection.mcp.commandOk,
|
|
90
|
+
...(inspection.mcp.otherServers === undefined
|
|
91
|
+
? {}
|
|
92
|
+
: { otherServers: inspection.mcp.otherServers }),
|
|
88
93
|
},
|
|
89
94
|
}),
|
|
90
95
|
};
|
|
@@ -102,6 +107,13 @@ export async function doctor(root, json) {
|
|
|
102
107
|
console.log(`Egress policy: ${egress?.mode === 'allowlist' ? `allowlist (${egress.allow.length} allowed host${egress.allow.length === 1 ? '' : 's'})` : 'warn (default)'}`);
|
|
103
108
|
console.log(`Hook on internal error: ${hookFailClosed ? 'fail-closed' : 'fail-open (default)'}`);
|
|
104
109
|
console.log(`Hook heartbeat: ${describeHeartbeatAge(hookLastRan)}`);
|
|
110
|
+
if (hookDecisions !== null) {
|
|
111
|
+
console.log(`Hook decisions (approx): ${hookDecisions.allow} allow, ${hookDecisions.deny} deny`);
|
|
112
|
+
}
|
|
113
|
+
const siblings = inspection.mcp?.otherServers ?? [];
|
|
114
|
+
if (siblings.length > 0) {
|
|
115
|
+
console.log(`Other MCP servers (outside envseal read protection): ${siblings.join(', ')}`);
|
|
116
|
+
}
|
|
105
117
|
console.log(`Missing required keys: ${status.missingRequired.length}`);
|
|
106
118
|
if (status.missingRequired.length > 0) {
|
|
107
119
|
for (const key of status.missingRequired) {
|
|
@@ -79,11 +79,20 @@ export function inspectCopilotSettings(root, options = {}) {
|
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
81
|
const entry = list.find((item) => entryName(item) === ENVSEAL_MCP_SERVER_NAME);
|
|
82
|
+
// Names only, never entry values: a sibling argv or env block can hold a
|
|
83
|
+
// real credential, and doctor output must not become a new exfil channel.
|
|
84
|
+
// List configs can repeat a name; report each server once.
|
|
85
|
+
const otherServers = [
|
|
86
|
+
...new Set(list
|
|
87
|
+
.map((item) => entryName(item))
|
|
88
|
+
.filter((name) => name !== undefined && name !== ENVSEAL_MCP_SERVER_NAME)),
|
|
89
|
+
].sort();
|
|
82
90
|
if (entry === undefined || isEmptyEnvsealStub(entry) || !looksLikeEnvsealServer(entry)) {
|
|
83
91
|
return {
|
|
84
92
|
wired: false,
|
|
85
93
|
status: entry === undefined ? 'missing' : 'stub',
|
|
86
94
|
commandOk: null,
|
|
95
|
+
otherServers,
|
|
87
96
|
message: `.vscode/settings.json github.copilot.mcp has no working envseal-mcp. ${hint}`,
|
|
88
97
|
};
|
|
89
98
|
}
|
|
@@ -94,6 +103,6 @@ export function inspectCopilotSettings(root, options = {}) {
|
|
|
94
103
|
message =
|
|
95
104
|
'Copilot MCP is configured, but the launch command did not report a version. Run `envseal init`. [VERIFY]';
|
|
96
105
|
}
|
|
97
|
-
return { wired: true, status: 'wired', commandOk, message };
|
|
106
|
+
return { wired: true, status: 'wired', commandOk, otherServers, message };
|
|
98
107
|
}
|
|
99
108
|
//# sourceMappingURL=copilot.js.map
|
|
@@ -13,7 +13,19 @@ export type McpInspection = {
|
|
|
13
13
|
message: string;
|
|
14
14
|
/** null when the launch command was not probed (npx is not side-effect free). */
|
|
15
15
|
commandOk: boolean | null;
|
|
16
|
+
/**
|
|
17
|
+
* Names of co-registered MCP servers besides envseal-mcp. Names only, never
|
|
18
|
+
* entry values: a sibling argv or env block can hold a real credential, and
|
|
19
|
+
* doctor output must not become a new exfil channel. Undefined when the host
|
|
20
|
+
* config shape carries no enumerable server list.
|
|
21
|
+
*/
|
|
22
|
+
otherServers?: string[];
|
|
16
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* Sorted names of every server in a `mcpServers`-style map except envseal-mcp.
|
|
26
|
+
* Keys only: callers must never forward the entry values.
|
|
27
|
+
*/
|
|
28
|
+
export declare function siblingServerNames(servers: Record<string, unknown>): string[];
|
|
17
29
|
/**
|
|
18
30
|
* Launch argv a host can spawn without a global `envseal-mcp` on PATH.
|
|
19
31
|
* Project MCP uses the workspace as cwd — never bake `--project` in.
|
package/dist/host-wiring/mcp.js
CHANGED
|
@@ -4,6 +4,15 @@ import { spawnSync } from 'node:child_process';
|
|
|
4
4
|
export const ENVSEAL_MCP_PACKAGE = '@envseal/mcp-server';
|
|
5
5
|
export const ENVSEAL_MCP_SERVER_NAME = 'envseal-mcp';
|
|
6
6
|
export const NPX_ARGS = ['-y', ENVSEAL_MCP_PACKAGE];
|
|
7
|
+
/**
|
|
8
|
+
* Sorted names of every server in a `mcpServers`-style map except envseal-mcp.
|
|
9
|
+
* Keys only: callers must never forward the entry values.
|
|
10
|
+
*/
|
|
11
|
+
export function siblingServerNames(servers) {
|
|
12
|
+
return Object.keys(servers)
|
|
13
|
+
.filter((name) => name !== ENVSEAL_MCP_SERVER_NAME)
|
|
14
|
+
.sort();
|
|
15
|
+
}
|
|
7
16
|
/**
|
|
8
17
|
* Launch argv a host can spawn without a global `envseal-mcp` on PATH.
|
|
9
18
|
* Project MCP uses the workspace as cwd — never bake `--project` in.
|
|
@@ -203,11 +212,13 @@ export function inspectMcpServersFile(path, label, options = {}) {
|
|
|
203
212
|
}
|
|
204
213
|
const entry = servers[ENVSEAL_MCP_SERVER_NAME];
|
|
205
214
|
const kind = classifyEntry(entry);
|
|
215
|
+
const otherServers = siblingServerNames(servers);
|
|
206
216
|
if (kind === 'missing') {
|
|
207
217
|
return {
|
|
208
218
|
wired: false,
|
|
209
219
|
status: 'missing',
|
|
210
220
|
commandOk: null,
|
|
221
|
+
otherServers,
|
|
211
222
|
message: `${label} has no envseal-mcp. ${hint}`,
|
|
212
223
|
};
|
|
213
224
|
}
|
|
@@ -216,6 +227,7 @@ export function inspectMcpServersFile(path, label, options = {}) {
|
|
|
216
227
|
wired: false,
|
|
217
228
|
status: 'stub',
|
|
218
229
|
commandOk: null,
|
|
230
|
+
otherServers,
|
|
219
231
|
message: `${label} envseal-mcp is the empty envseal-mcp stub (not on PATH for the host). ${hint}`,
|
|
220
232
|
};
|
|
221
233
|
}
|
|
@@ -225,7 +237,7 @@ export function inspectMcpServersFile(path, label, options = {}) {
|
|
|
225
237
|
if (commandOk === false) {
|
|
226
238
|
message = `MCP is configured in ${label}, but the launch command did not report a version. Run \`envseal init\` if the host cannot connect.`;
|
|
227
239
|
}
|
|
228
|
-
return { wired: true, status: 'wired', commandOk, message };
|
|
240
|
+
return { wired: true, status: 'wired', commandOk, otherServers, message };
|
|
229
241
|
}
|
|
230
242
|
/** Map an inspection to the doctor `agentWiring.mcp` field. */
|
|
231
243
|
export function mcpWiringState(inspection) {
|
package/dist/host-wiring/zed.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { join } from 'node:path';
|
|
3
|
-
import { ENVSEAL_MCP_SERVER_NAME, isRecord, mcpLaunch, nextEnvsealEntry, parseJsonObject, writeJson, classifyEntry, probeVersion, } from './mcp.js';
|
|
3
|
+
import { ENVSEAL_MCP_SERVER_NAME, isRecord, mcpLaunch, nextEnvsealEntry, parseJsonObject, writeJson, classifyEntry, probeVersion, siblingServerNames, } from './mcp.js';
|
|
4
4
|
function zedHint(platform) {
|
|
5
5
|
const launch = mcpLaunch(platform);
|
|
6
6
|
return `Run \`envseal init\` to merge { "mcp": { "${ENVSEAL_MCP_SERVER_NAME}": ${JSON.stringify(launch)} } } into .zed/settings.json. [VERIFY]`;
|
|
@@ -69,11 +69,13 @@ export function inspectZedSettings(root, options = {}) {
|
|
|
69
69
|
}
|
|
70
70
|
const entry = mcp[ENVSEAL_MCP_SERVER_NAME];
|
|
71
71
|
const kind = classifyEntry(entry);
|
|
72
|
+
const otherServers = siblingServerNames(mcp);
|
|
72
73
|
if (kind === 'missing') {
|
|
73
74
|
return {
|
|
74
75
|
wired: false,
|
|
75
76
|
status: 'missing',
|
|
76
77
|
commandOk: null,
|
|
78
|
+
otherServers,
|
|
77
79
|
message: `.zed/settings.json has no envseal-mcp. ${hint}`,
|
|
78
80
|
};
|
|
79
81
|
}
|
|
@@ -82,6 +84,7 @@ export function inspectZedSettings(root, options = {}) {
|
|
|
82
84
|
wired: false,
|
|
83
85
|
status: 'stub',
|
|
84
86
|
commandOk: null,
|
|
87
|
+
otherServers,
|
|
85
88
|
message: `.zed/settings.json envseal-mcp is the empty stub. ${hint}`,
|
|
86
89
|
};
|
|
87
90
|
}
|
|
@@ -92,6 +95,6 @@ export function inspectZedSettings(root, options = {}) {
|
|
|
92
95
|
message =
|
|
93
96
|
'Zed MCP is configured, but the launch command did not report a version. Run `envseal init`. [VERIFY]';
|
|
94
97
|
}
|
|
95
|
-
return { wired: true, status: 'wired', commandOk, message };
|
|
98
|
+
return { wired: true, status: 'wired', commandOk, otherServers, message };
|
|
96
99
|
}
|
|
97
100
|
//# sourceMappingURL=zed.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@envseal/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -23,13 +23,13 @@
|
|
|
23
23
|
"provenance": true
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@envseal/
|
|
27
|
-
"@envseal/prompters": "0.1.
|
|
28
|
-
"@envseal/
|
|
29
|
-
"@envseal/
|
|
30
|
-
"@envseal/
|
|
31
|
-
"@envseal/http-server": "0.1.
|
|
32
|
-
"@envseal/
|
|
26
|
+
"@envseal/core": "0.1.7",
|
|
27
|
+
"@envseal/prompters": "0.1.7",
|
|
28
|
+
"@envseal/protocol": "0.1.7",
|
|
29
|
+
"@envseal/detector": "0.1.7",
|
|
30
|
+
"@envseal/registry": "0.1.7",
|
|
31
|
+
"@envseal/http-server": "0.1.7",
|
|
32
|
+
"@envseal/mcp-server": "0.1.7"
|
|
33
33
|
},
|
|
34
34
|
"repository": {
|
|
35
35
|
"type": "git",
|