@enactprotocol/cli 1.2.13 → 2.0.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/README.md +88 -0
- package/package.json +34 -38
- package/src/commands/auth/index.ts +940 -0
- package/src/commands/cache/index.ts +361 -0
- package/src/commands/config/README.md +239 -0
- package/src/commands/config/index.ts +164 -0
- package/src/commands/env/README.md +197 -0
- package/src/commands/env/index.ts +392 -0
- package/src/commands/exec/README.md +110 -0
- package/src/commands/exec/index.ts +195 -0
- package/src/commands/get/index.ts +198 -0
- package/src/commands/index.ts +30 -0
- package/src/commands/inspect/index.ts +264 -0
- package/src/commands/install/README.md +146 -0
- package/src/commands/install/index.ts +682 -0
- package/src/commands/list/README.md +115 -0
- package/src/commands/list/index.ts +138 -0
- package/src/commands/publish/index.ts +350 -0
- package/src/commands/report/index.ts +366 -0
- package/src/commands/run/README.md +124 -0
- package/src/commands/run/index.ts +686 -0
- package/src/commands/search/index.ts +368 -0
- package/src/commands/setup/index.ts +274 -0
- package/src/commands/sign/index.ts +652 -0
- package/src/commands/trust/README.md +214 -0
- package/src/commands/trust/index.ts +453 -0
- package/src/commands/unyank/index.ts +107 -0
- package/src/commands/yank/index.ts +143 -0
- package/src/index.ts +96 -0
- package/src/types.ts +81 -0
- package/src/utils/errors.ts +409 -0
- package/src/utils/exit-codes.ts +159 -0
- package/src/utils/ignore.ts +147 -0
- package/src/utils/index.ts +107 -0
- package/src/utils/output.ts +242 -0
- package/src/utils/spinner.ts +214 -0
- package/tests/commands/auth.test.ts +217 -0
- package/tests/commands/cache.test.ts +286 -0
- package/tests/commands/config.test.ts +277 -0
- package/tests/commands/env.test.ts +293 -0
- package/tests/commands/exec.test.ts +112 -0
- package/tests/commands/get.test.ts +179 -0
- package/tests/commands/inspect.test.ts +201 -0
- package/tests/commands/install-integration.test.ts +343 -0
- package/tests/commands/install.test.ts +288 -0
- package/tests/commands/list.test.ts +160 -0
- package/tests/commands/publish.test.ts +186 -0
- package/tests/commands/report.test.ts +194 -0
- package/tests/commands/run.test.ts +231 -0
- package/tests/commands/search.test.ts +131 -0
- package/tests/commands/sign.test.ts +164 -0
- package/tests/commands/trust.test.ts +236 -0
- package/tests/commands/unyank.test.ts +114 -0
- package/tests/commands/yank.test.ts +154 -0
- package/tests/e2e.test.ts +554 -0
- package/tests/fixtures/calculator/enact.yaml +34 -0
- package/tests/fixtures/echo-tool/enact.md +31 -0
- package/tests/fixtures/env-tool/enact.yaml +19 -0
- package/tests/fixtures/greeter/enact.yaml +18 -0
- package/tests/fixtures/invalid-tool/enact.yaml +4 -0
- package/tests/index.test.ts +8 -0
- package/tests/types.test.ts +84 -0
- package/tests/utils/errors.test.ts +303 -0
- package/tests/utils/exit-codes.test.ts +189 -0
- package/tests/utils/ignore.test.ts +461 -0
- package/tests/utils/output.test.ts +126 -0
- package/tsconfig.json +17 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/dist/index.js +0 -231612
- package/dist/index.js.bak +0 -231611
- package/dist/web/static/app.js +0 -663
- package/dist/web/static/index.html +0 -117
- package/dist/web/static/style.css +0 -291
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* enact cache command
|
|
3
|
+
*
|
|
4
|
+
* Manage the local tool cache.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { existsSync, readdirSync, rmSync, statSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { getCacheDir, tryLoadManifestFromDir } from "@enactprotocol/shared";
|
|
10
|
+
import type { Command } from "commander";
|
|
11
|
+
import type { CommandContext, GlobalOptions } from "../../types";
|
|
12
|
+
import {
|
|
13
|
+
type TableColumn,
|
|
14
|
+
confirm,
|
|
15
|
+
dim,
|
|
16
|
+
error,
|
|
17
|
+
formatError,
|
|
18
|
+
header,
|
|
19
|
+
info,
|
|
20
|
+
json,
|
|
21
|
+
keyValue,
|
|
22
|
+
newline,
|
|
23
|
+
success,
|
|
24
|
+
table,
|
|
25
|
+
warning,
|
|
26
|
+
} from "../../utils";
|
|
27
|
+
|
|
28
|
+
interface CacheOptions extends GlobalOptions {
|
|
29
|
+
force?: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface CachedTool {
|
|
33
|
+
name: string;
|
|
34
|
+
version: string;
|
|
35
|
+
size: string;
|
|
36
|
+
path: string;
|
|
37
|
+
[key: string]: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Format bytes to human readable
|
|
42
|
+
*/
|
|
43
|
+
function formatSize(bytes: number): string {
|
|
44
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
45
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
46
|
+
if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
47
|
+
return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get directory size recursively
|
|
52
|
+
*/
|
|
53
|
+
function getDirSize(dirPath: string): number {
|
|
54
|
+
let size = 0;
|
|
55
|
+
try {
|
|
56
|
+
const entries = readdirSync(dirPath, { withFileTypes: true });
|
|
57
|
+
for (const entry of entries) {
|
|
58
|
+
const entryPath = join(dirPath, entry.name);
|
|
59
|
+
if (entry.isDirectory()) {
|
|
60
|
+
size += getDirSize(entryPath);
|
|
61
|
+
} else {
|
|
62
|
+
size += statSync(entryPath).size;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
} catch {
|
|
66
|
+
// Ignore errors
|
|
67
|
+
}
|
|
68
|
+
return size;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* List cached tools
|
|
73
|
+
*/
|
|
74
|
+
function listCachedTools(cacheDir: string): CachedTool[] {
|
|
75
|
+
const tools: CachedTool[] = [];
|
|
76
|
+
|
|
77
|
+
if (!existsSync(cacheDir)) {
|
|
78
|
+
return tools;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function walkDir(dir: string, prefix = ""): void {
|
|
82
|
+
try {
|
|
83
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
84
|
+
|
|
85
|
+
for (const entry of entries) {
|
|
86
|
+
if (!entry.isDirectory()) continue;
|
|
87
|
+
|
|
88
|
+
const entryPath = join(dir, entry.name);
|
|
89
|
+
const toolName = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
90
|
+
|
|
91
|
+
const loaded = tryLoadManifestFromDir(entryPath);
|
|
92
|
+
if (loaded) {
|
|
93
|
+
const size = getDirSize(entryPath);
|
|
94
|
+
tools.push({
|
|
95
|
+
name: loaded.manifest.name,
|
|
96
|
+
version: loaded.manifest.version ?? "-",
|
|
97
|
+
size: formatSize(size),
|
|
98
|
+
path: entryPath,
|
|
99
|
+
});
|
|
100
|
+
} else {
|
|
101
|
+
walkDir(entryPath, toolName);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
// Ignore errors
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
walkDir(cacheDir);
|
|
110
|
+
return tools;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Cache list handler
|
|
115
|
+
*/
|
|
116
|
+
async function listHandler(options: CacheOptions, _ctx: CommandContext): Promise<void> {
|
|
117
|
+
const cacheDir = getCacheDir();
|
|
118
|
+
const tools = listCachedTools(cacheDir);
|
|
119
|
+
|
|
120
|
+
if (options.json) {
|
|
121
|
+
json({ cacheDir, tools, count: tools.length });
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
header("Cached Tools");
|
|
126
|
+
newline();
|
|
127
|
+
|
|
128
|
+
if (tools.length === 0) {
|
|
129
|
+
info("No tools cached.");
|
|
130
|
+
dim(`Cache directory: ${cacheDir}`);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const columns: TableColumn[] = [
|
|
135
|
+
{ key: "name", header: "Name", width: 35 },
|
|
136
|
+
{ key: "version", header: "Version", width: 12 },
|
|
137
|
+
{ key: "size", header: "Size", width: 10 },
|
|
138
|
+
];
|
|
139
|
+
|
|
140
|
+
if (options.verbose) {
|
|
141
|
+
columns.push({ key: "path", header: "Path", width: 50 });
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
table(tools, columns);
|
|
145
|
+
newline();
|
|
146
|
+
|
|
147
|
+
const totalSize = tools.reduce((sum, t) => {
|
|
148
|
+
const match = t.size.match(/^([\d.]+)\s*(\w+)$/);
|
|
149
|
+
if (!match) return sum;
|
|
150
|
+
const [, num, unit] = match;
|
|
151
|
+
const multipliers: Record<string, number> = {
|
|
152
|
+
B: 1,
|
|
153
|
+
KB: 1024,
|
|
154
|
+
MB: 1024 * 1024,
|
|
155
|
+
GB: 1024 * 1024 * 1024,
|
|
156
|
+
};
|
|
157
|
+
return sum + Number.parseFloat(num ?? "0") * (multipliers[unit ?? "B"] ?? 1);
|
|
158
|
+
}, 0);
|
|
159
|
+
|
|
160
|
+
dim(`Total: ${tools.length} tool(s), ${formatSize(totalSize)}`);
|
|
161
|
+
dim(`Cache directory: ${cacheDir}`);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Cache clean handler - remove old/unused tools
|
|
166
|
+
*/
|
|
167
|
+
async function cleanHandler(options: CacheOptions, ctx: CommandContext): Promise<void> {
|
|
168
|
+
const cacheDir = getCacheDir();
|
|
169
|
+
const tools = listCachedTools(cacheDir);
|
|
170
|
+
|
|
171
|
+
if (tools.length === 0) {
|
|
172
|
+
info("Cache is already empty.");
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// For now, clean removes everything (future: could be smarter)
|
|
177
|
+
if (!options.force && ctx.isInteractive) {
|
|
178
|
+
const shouldProceed = await confirm(`Remove ${tools.length} cached tool(s)?`);
|
|
179
|
+
if (!shouldProceed) {
|
|
180
|
+
info("Cancelled.");
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
let removed = 0;
|
|
186
|
+
for (const tool of tools) {
|
|
187
|
+
try {
|
|
188
|
+
rmSync(tool.path, { recursive: true, force: true });
|
|
189
|
+
removed++;
|
|
190
|
+
if (options.verbose) {
|
|
191
|
+
dim(`Removed: ${tool.name}@${tool.version}`);
|
|
192
|
+
}
|
|
193
|
+
} catch {
|
|
194
|
+
warning(`Failed to remove: ${tool.path}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (options.json) {
|
|
199
|
+
json({ removed, total: tools.length });
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
success(`Removed ${removed} cached tool(s)`);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Cache clear handler - remove entire cache
|
|
208
|
+
*/
|
|
209
|
+
async function clearHandler(options: CacheOptions, ctx: CommandContext): Promise<void> {
|
|
210
|
+
const cacheDir = getCacheDir();
|
|
211
|
+
|
|
212
|
+
if (!existsSync(cacheDir)) {
|
|
213
|
+
info("Cache directory does not exist.");
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const size = getDirSize(cacheDir);
|
|
218
|
+
|
|
219
|
+
if (!options.force && ctx.isInteractive) {
|
|
220
|
+
const shouldProceed = await confirm(`Clear entire cache (${formatSize(size)})?`);
|
|
221
|
+
if (!shouldProceed) {
|
|
222
|
+
info("Cancelled.");
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
rmSync(cacheDir, { recursive: true, force: true });
|
|
229
|
+
|
|
230
|
+
if (options.json) {
|
|
231
|
+
json({ cleared: true, size: formatSize(size) });
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
success(`Cleared cache (${formatSize(size)})`);
|
|
236
|
+
} catch (err) {
|
|
237
|
+
error(`Failed to clear cache: ${formatError(err)}`);
|
|
238
|
+
process.exit(1);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Cache info handler
|
|
244
|
+
*/
|
|
245
|
+
async function infoHandler(options: CacheOptions, _ctx: CommandContext): Promise<void> {
|
|
246
|
+
const cacheDir = getCacheDir();
|
|
247
|
+
const exists = existsSync(cacheDir);
|
|
248
|
+
const tools = exists ? listCachedTools(cacheDir) : [];
|
|
249
|
+
const size = exists ? getDirSize(cacheDir) : 0;
|
|
250
|
+
|
|
251
|
+
if (options.json) {
|
|
252
|
+
json({
|
|
253
|
+
directory: cacheDir,
|
|
254
|
+
exists,
|
|
255
|
+
toolCount: tools.length,
|
|
256
|
+
totalSize: size,
|
|
257
|
+
totalSizeFormatted: formatSize(size),
|
|
258
|
+
});
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
header("Cache Information");
|
|
263
|
+
newline();
|
|
264
|
+
|
|
265
|
+
keyValue("Directory", cacheDir);
|
|
266
|
+
keyValue("Exists", exists ? "Yes" : "No");
|
|
267
|
+
keyValue("Tools", String(tools.length));
|
|
268
|
+
keyValue("Total Size", formatSize(size));
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Configure the cache command
|
|
273
|
+
*/
|
|
274
|
+
export function configureCacheCommand(program: Command): void {
|
|
275
|
+
const cache = program.command("cache").description("Manage the local tool cache");
|
|
276
|
+
|
|
277
|
+
cache
|
|
278
|
+
.command("list")
|
|
279
|
+
.alias("ls")
|
|
280
|
+
.description("List cached tools")
|
|
281
|
+
.option("-v, --verbose", "Show detailed output including paths")
|
|
282
|
+
.option("--json", "Output as JSON")
|
|
283
|
+
.action(async (options: CacheOptions) => {
|
|
284
|
+
const ctx: CommandContext = {
|
|
285
|
+
cwd: process.cwd(),
|
|
286
|
+
options,
|
|
287
|
+
isCI: Boolean(process.env.CI),
|
|
288
|
+
isInteractive: process.stdout.isTTY ?? false,
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
try {
|
|
292
|
+
await listHandler(options, ctx);
|
|
293
|
+
} catch (err) {
|
|
294
|
+
error(formatError(err));
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
cache
|
|
300
|
+
.command("clean")
|
|
301
|
+
.description("Remove old or unused cached tools")
|
|
302
|
+
.option("-f, --force", "Skip confirmation")
|
|
303
|
+
.option("-v, --verbose", "Show detailed output")
|
|
304
|
+
.option("--json", "Output as JSON")
|
|
305
|
+
.action(async (options: CacheOptions) => {
|
|
306
|
+
const ctx: CommandContext = {
|
|
307
|
+
cwd: process.cwd(),
|
|
308
|
+
options,
|
|
309
|
+
isCI: Boolean(process.env.CI),
|
|
310
|
+
isInteractive: process.stdout.isTTY ?? false,
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
try {
|
|
314
|
+
await cleanHandler(options, ctx);
|
|
315
|
+
} catch (err) {
|
|
316
|
+
error(formatError(err));
|
|
317
|
+
process.exit(1);
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
cache
|
|
322
|
+
.command("clear")
|
|
323
|
+
.description("Clear the entire cache")
|
|
324
|
+
.option("-f, --force", "Skip confirmation")
|
|
325
|
+
.option("--json", "Output as JSON")
|
|
326
|
+
.action(async (options: CacheOptions) => {
|
|
327
|
+
const ctx: CommandContext = {
|
|
328
|
+
cwd: process.cwd(),
|
|
329
|
+
options,
|
|
330
|
+
isCI: Boolean(process.env.CI),
|
|
331
|
+
isInteractive: process.stdout.isTTY ?? false,
|
|
332
|
+
};
|
|
333
|
+
|
|
334
|
+
try {
|
|
335
|
+
await clearHandler(options, ctx);
|
|
336
|
+
} catch (err) {
|
|
337
|
+
error(formatError(err));
|
|
338
|
+
process.exit(1);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
cache
|
|
343
|
+
.command("info")
|
|
344
|
+
.description("Show cache information")
|
|
345
|
+
.option("--json", "Output as JSON")
|
|
346
|
+
.action(async (options: CacheOptions) => {
|
|
347
|
+
const ctx: CommandContext = {
|
|
348
|
+
cwd: process.cwd(),
|
|
349
|
+
options,
|
|
350
|
+
isCI: Boolean(process.env.CI),
|
|
351
|
+
isInteractive: process.stdout.isTTY ?? false,
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
try {
|
|
355
|
+
await infoHandler(options, ctx);
|
|
356
|
+
} catch (err) {
|
|
357
|
+
error(formatError(err));
|
|
358
|
+
process.exit(1);
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
# enact config
|
|
2
|
+
|
|
3
|
+
Manage CLI configuration.
|
|
4
|
+
|
|
5
|
+
## Synopsis
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
enact config <subcommand> [options]
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Description
|
|
12
|
+
|
|
13
|
+
The `config` command manages Enact's global configuration settings. Configuration is stored in `~/.enact/config.yaml` and controls default behaviors, trust settings, and other preferences.
|
|
14
|
+
|
|
15
|
+
## Subcommands
|
|
16
|
+
|
|
17
|
+
### config get
|
|
18
|
+
|
|
19
|
+
Get a configuration value.
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
enact config get <key> [options]
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Arguments:**
|
|
26
|
+
| Argument | Description |
|
|
27
|
+
|----------|-------------|
|
|
28
|
+
| `key` | Configuration key using dot notation |
|
|
29
|
+
|
|
30
|
+
**Options:**
|
|
31
|
+
| Option | Description |
|
|
32
|
+
|--------|-------------|
|
|
33
|
+
| `--json` | Output as JSON |
|
|
34
|
+
|
|
35
|
+
**Examples:**
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
# Get trust policy
|
|
39
|
+
enact config get trust.policy
|
|
40
|
+
|
|
41
|
+
# Get as JSON
|
|
42
|
+
enact config get trust.publishers --json
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### config set
|
|
46
|
+
|
|
47
|
+
Set a configuration value.
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
enact config set <key> <value> [options]
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Arguments:**
|
|
54
|
+
| Argument | Description |
|
|
55
|
+
|----------|-------------|
|
|
56
|
+
| `key` | Configuration key using dot notation |
|
|
57
|
+
| `value` | Value to set (use JSON for arrays/objects) |
|
|
58
|
+
|
|
59
|
+
**Options:**
|
|
60
|
+
| Option | Description |
|
|
61
|
+
|--------|-------------|
|
|
62
|
+
| `--json` | Output as JSON |
|
|
63
|
+
|
|
64
|
+
**Examples:**
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# Set trust policy
|
|
68
|
+
enact config set trust.policy strict
|
|
69
|
+
|
|
70
|
+
# Set an array value (use JSON)
|
|
71
|
+
enact config set trust.publishers '["alice","bob"]'
|
|
72
|
+
|
|
73
|
+
# Set a boolean
|
|
74
|
+
enact config set execution.sandbox true
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### config list
|
|
78
|
+
|
|
79
|
+
List all configuration values.
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
enact config list [options]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**Options:**
|
|
86
|
+
| Option | Description |
|
|
87
|
+
|--------|-------------|
|
|
88
|
+
| `--json` | Output as JSON |
|
|
89
|
+
|
|
90
|
+
**Examples:**
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
$ enact config list
|
|
94
|
+
|
|
95
|
+
Configuration file: /Users/you/.enact/config.yaml
|
|
96
|
+
|
|
97
|
+
trust.publishers: ["alice","EnactProtocol"]
|
|
98
|
+
trust.auditors: ["github:securityteam"]
|
|
99
|
+
trust.policy: warn
|
|
100
|
+
execution.timeout: 300
|
|
101
|
+
execution.sandbox: true
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## Configuration Keys
|
|
105
|
+
|
|
106
|
+
### Trust Settings
|
|
107
|
+
|
|
108
|
+
| Key | Type | Default | Description |
|
|
109
|
+
|-----|------|---------|-------------|
|
|
110
|
+
| `trust.publishers` | `string[]` | `[]` | Trusted publisher names |
|
|
111
|
+
| `trust.auditors` | `string[]` | `[]` | Trusted auditor identities |
|
|
112
|
+
| `trust.policy` | `string` | `"warn"` | Policy for untrusted tools: `strict`, `warn`, `allow` |
|
|
113
|
+
|
|
114
|
+
### Execution Settings
|
|
115
|
+
|
|
116
|
+
| Key | Type | Default | Description |
|
|
117
|
+
|-----|------|---------|-------------|
|
|
118
|
+
| `execution.timeout` | `number` | `300` | Default timeout in seconds |
|
|
119
|
+
| `execution.sandbox` | `boolean` | `true` | Enable sandboxing by default |
|
|
120
|
+
|
|
121
|
+
### Output Settings
|
|
122
|
+
|
|
123
|
+
| Key | Type | Default | Description |
|
|
124
|
+
|-----|------|---------|-------------|
|
|
125
|
+
| `output.json` | `boolean` | `false` | Default to JSON output |
|
|
126
|
+
| `output.verbose` | `boolean` | `false` | Enable verbose output |
|
|
127
|
+
|
|
128
|
+
## Dot Notation
|
|
129
|
+
|
|
130
|
+
Configuration keys use dot notation to access nested values:
|
|
131
|
+
|
|
132
|
+
```yaml
|
|
133
|
+
# config.yaml
|
|
134
|
+
trust:
|
|
135
|
+
publishers:
|
|
136
|
+
- alice
|
|
137
|
+
- bob
|
|
138
|
+
policy: warn
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Access with:
|
|
142
|
+
- `trust.policy` → `warn`
|
|
143
|
+
- `trust.publishers` → `["alice","bob"]`
|
|
144
|
+
|
|
145
|
+
## Configuration File
|
|
146
|
+
|
|
147
|
+
The configuration file is located at `~/.enact/config.yaml`. You can edit it directly or use the `config` commands.
|
|
148
|
+
|
|
149
|
+
### Example Configuration
|
|
150
|
+
|
|
151
|
+
```yaml
|
|
152
|
+
# ~/.enact/config.yaml
|
|
153
|
+
trust:
|
|
154
|
+
publishers:
|
|
155
|
+
- EnactProtocol
|
|
156
|
+
- mycompany
|
|
157
|
+
auditors:
|
|
158
|
+
- github:security-team
|
|
159
|
+
policy: warn
|
|
160
|
+
|
|
161
|
+
execution:
|
|
162
|
+
timeout: 300
|
|
163
|
+
sandbox: true
|
|
164
|
+
|
|
165
|
+
output:
|
|
166
|
+
json: false
|
|
167
|
+
verbose: false
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## JSON Output
|
|
171
|
+
|
|
172
|
+
All subcommands support `--json` for machine-readable output:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
$ enact config list --json
|
|
176
|
+
{
|
|
177
|
+
"trust": {
|
|
178
|
+
"publishers": ["alice"],
|
|
179
|
+
"auditors": [],
|
|
180
|
+
"policy": "warn"
|
|
181
|
+
},
|
|
182
|
+
"execution": {
|
|
183
|
+
"timeout": 300
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Examples
|
|
189
|
+
|
|
190
|
+
### Initial Setup
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
# Set up default trust
|
|
194
|
+
enact config set trust.policy warn
|
|
195
|
+
|
|
196
|
+
# Trust official tools
|
|
197
|
+
enact config set trust.publishers '["EnactProtocol"]'
|
|
198
|
+
|
|
199
|
+
# Configure execution defaults
|
|
200
|
+
enact config set execution.timeout 600
|
|
201
|
+
enact config set execution.sandbox true
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### View Current Settings
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
# See everything
|
|
208
|
+
enact config list
|
|
209
|
+
|
|
210
|
+
# Check specific setting
|
|
211
|
+
enact config get trust.policy
|
|
212
|
+
|
|
213
|
+
# Export for backup
|
|
214
|
+
enact config list --json > enact-config-backup.json
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Scripting
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
# Get value for use in script
|
|
221
|
+
policy=$(enact config get trust.policy --json | jq -r '.value')
|
|
222
|
+
|
|
223
|
+
# Conditionally run based on config
|
|
224
|
+
if [[ "$policy" == "strict" ]]; then
|
|
225
|
+
echo "Running in strict mode"
|
|
226
|
+
fi
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Exit Codes
|
|
230
|
+
|
|
231
|
+
| Code | Description |
|
|
232
|
+
|------|-------------|
|
|
233
|
+
| `0` | Success |
|
|
234
|
+
| `1` | Error |
|
|
235
|
+
|
|
236
|
+
## See Also
|
|
237
|
+
|
|
238
|
+
- [enact trust](../trust/README.md) - Shorthand commands for trust management
|
|
239
|
+
- [enact env](../env/README.md) - Manage environment variables
|