@envseal/cli 0.1.2 → 0.1.3
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/bin.js +1 -1
- package/dist/commands/run.js +13 -15
- package/dist/exit-codes.js +1 -0
- package/dist/test-prompter.js +16 -8
- package/package.json +8 -8
package/dist/bin.js
CHANGED
|
@@ -13,7 +13,7 @@ import { doctor } from './commands/doctor.js';
|
|
|
13
13
|
import { revoke } from './commands/revoke.js';
|
|
14
14
|
import { mcp } from './commands/mcp.js';
|
|
15
15
|
import { init } from './commands/init.js';
|
|
16
|
-
const VERSION = '0.1.
|
|
16
|
+
const VERSION = '0.1.3';
|
|
17
17
|
async function main() {
|
|
18
18
|
const argv = process.argv.slice(2);
|
|
19
19
|
if (argv.length === 0 || argv[0] === '--help' || argv[0] === '-h') {
|
package/dist/commands/run.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createInterface } from 'node:readline';
|
|
2
2
|
import { SepError } from '@envseal/protocol';
|
|
3
|
+
import { useConfirmationBody } from '@envseal/core';
|
|
3
4
|
import { emit, fail } from '../output.js';
|
|
4
5
|
import { createBroker } from '../cli-utils.js';
|
|
5
6
|
import { loadManifest, projectPaths } from '@envseal/core';
|
|
@@ -12,9 +13,11 @@ import { finish } from '../exit.js';
|
|
|
12
13
|
* prompt reads from the controlling terminal, so it still works when stdout is
|
|
13
14
|
* being piped.
|
|
14
15
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
16
|
+
* The dialog body comes from the SAME useConfirmationBody the MCP and SDK
|
|
17
|
+
* bindings render — one escaping/fingerprint implementation for every
|
|
18
|
+
* surface. Fails closed: no TTY and no --yes means no approval. That is the
|
|
19
|
+
* right default, because the alternative is a CI job silently handing
|
|
20
|
+
* credentials to whatever it was told to run.
|
|
18
21
|
*/
|
|
19
22
|
async function confirmInteractive(info) {
|
|
20
23
|
if (process.env.ENVSEAL_ASSUME_YES === '1')
|
|
@@ -23,23 +26,18 @@ async function confirmInteractive(info) {
|
|
|
23
26
|
// Distinct from a refusal. Reporting "the user denied the confirmation" when
|
|
24
27
|
// no human was ever asked is actively misleading, and it is the shell-only
|
|
25
28
|
// agents of Tier 4 that hit this path — the ones this binding exists for.
|
|
29
|
+
// Deliberately silent about HOW to proceed headlessly: this message lands in
|
|
30
|
+
// agent-visible stderr, and advertising the bypass here handed every reader
|
|
31
|
+
// a one-liner to skip the dialog entirely (documented in docs/ci.md instead).
|
|
26
32
|
throw new SepError({
|
|
27
33
|
code: 'SEP_NO_INTERACTIVE_SURFACE',
|
|
28
34
|
userMessage: 'envseal run needs confirmation before injecting secrets, but there is no terminal to ask on. ' +
|
|
29
|
-
'Re-run in an interactive shell
|
|
35
|
+
'Nothing was run and no value was read. Re-run it yourself in an interactive shell to review and ' +
|
|
36
|
+
'approve the command; see docs/ci.md for the supported headless pipeline setup.',
|
|
30
37
|
});
|
|
31
38
|
}
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
'envseal is about to run a command with secrets in its environment:',
|
|
35
|
-
` command: ${info.command.join(' ')}`,
|
|
36
|
-
` keys: ${info.keys.join(', ')}`,
|
|
37
|
-
];
|
|
38
|
-
if (info.networkEgress) {
|
|
39
|
-
lines.push(' WARNING: this command can make network requests, so it could send', ' these values somewhere. Only continue if you trust it.');
|
|
40
|
-
}
|
|
41
|
-
lines.push('');
|
|
42
|
-
process.stderr.write(lines.join('\n'));
|
|
39
|
+
const body = useConfirmationBody(info, process.cwd());
|
|
40
|
+
process.stderr.write(`\n${body}\n\n`);
|
|
43
41
|
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
44
42
|
try {
|
|
45
43
|
const answer = await new Promise((resolve) => {
|
package/dist/exit-codes.js
CHANGED
package/dist/test-prompter.js
CHANGED
|
@@ -17,14 +17,22 @@ export function createStubPrompter(value) {
|
|
|
17
17
|
return {
|
|
18
18
|
id: 'ide',
|
|
19
19
|
available: async () => true,
|
|
20
|
-
prompt: async (req) =>
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
prompt: async (req) => {
|
|
21
|
+
// Announce the stub on stderr, mirroring probe-approval.ts's
|
|
22
|
+
// ENVSEAL_TEST_APPROVAL notice: any answer that did not come from a
|
|
23
|
+
// human must be visible in the transcript. A model that discovers the
|
|
24
|
+
// two-variable gate cannot use it as a silent approval oracle.
|
|
25
|
+
process.stderr.write(`ENVSEAL_TEST_MODE: prompter is a STUB — key(s) [${req.keys.map((k) => k.key).join(', ')}] ` +
|
|
26
|
+
`answered from ENVSEAL_TEST_PROMPTER_VALUE with no UI.\n`);
|
|
27
|
+
return {
|
|
28
|
+
ticket: req.ticket,
|
|
29
|
+
results: req.keys.map((k) => ({
|
|
30
|
+
key: k.key,
|
|
31
|
+
outcome: 'entered',
|
|
32
|
+
value: secretFromUtf8(value),
|
|
33
|
+
})),
|
|
34
|
+
};
|
|
35
|
+
},
|
|
28
36
|
cancel: async () => {
|
|
29
37
|
/* nothing to tear down */
|
|
30
38
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@envseal/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
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/
|
|
28
|
-
"@envseal/
|
|
29
|
-
"@envseal/
|
|
30
|
-
"@envseal/
|
|
31
|
-
"@envseal/
|
|
32
|
-
"@envseal/http-server": "0.1.
|
|
26
|
+
"@envseal/core": "0.1.3",
|
|
27
|
+
"@envseal/prompters": "0.1.3",
|
|
28
|
+
"@envseal/protocol": "0.1.3",
|
|
29
|
+
"@envseal/registry": "0.1.3",
|
|
30
|
+
"@envseal/detector": "0.1.3",
|
|
31
|
+
"@envseal/mcp-server": "0.1.3",
|
|
32
|
+
"@envseal/http-server": "0.1.3"
|
|
33
33
|
},
|
|
34
34
|
"repository": {
|
|
35
35
|
"type": "git",
|