@peac/cli 0.9.18 → 0.10.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/LICENSE +190 -0
- package/dist/cli.js +3 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/bundle.d.ts +16 -0
- package/dist/commands/bundle.d.ts.map +1 -0
- package/dist/commands/bundle.js +363 -0
- package/dist/commands/bundle.js.map +1 -0
- package/dist/commands/policy.d.ts +7 -0
- package/dist/commands/policy.d.ts.map +1 -1
- package/dist/commands/policy.js +444 -96
- package/dist/commands/policy.js.map +1 -1
- package/dist/index.js +26 -22
- package/dist/index.js.map +1 -1
- package/package.json +15 -14
package/dist/commands/policy.js
CHANGED
|
@@ -7,6 +7,13 @@
|
|
|
7
7
|
* - validate: Validate policy syntax and schema
|
|
8
8
|
* - explain: Debug rule matching
|
|
9
9
|
* - generate: Compile policy to deployment artifacts
|
|
10
|
+
* - list-profiles: List available policy profiles (v0.9.23+)
|
|
11
|
+
* - show-profile: Show profile details (v0.9.23+)
|
|
12
|
+
*
|
|
13
|
+
* Automation flags (v0.9.23+):
|
|
14
|
+
* - --json: Machine-readable JSON output
|
|
15
|
+
* - --yes: Skip confirmation prompts (auto-confirm)
|
|
16
|
+
* - --strict: Exit non-zero on warnings
|
|
10
17
|
*/
|
|
11
18
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
19
|
if (k2 === undefined) k2 = k;
|
|
@@ -47,7 +54,42 @@ const commander_1 = require("commander");
|
|
|
47
54
|
const fs = __importStar(require("fs"));
|
|
48
55
|
const path = __importStar(require("path"));
|
|
49
56
|
const policy_kit_1 = require("@peac/policy-kit");
|
|
50
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Get global options from parent command
|
|
59
|
+
*/
|
|
60
|
+
function getGlobalOptions(cmd) {
|
|
61
|
+
const parent = cmd.parent;
|
|
62
|
+
if (!parent)
|
|
63
|
+
return {};
|
|
64
|
+
return parent.opts();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Output result - handles JSON vs human-readable format
|
|
68
|
+
*/
|
|
69
|
+
function output(data, opts, humanMessage) {
|
|
70
|
+
if (opts.json) {
|
|
71
|
+
console.log(JSON.stringify(data, null, 2));
|
|
72
|
+
}
|
|
73
|
+
else if (humanMessage) {
|
|
74
|
+
console.log(humanMessage);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Output error - handles JSON vs human-readable format
|
|
79
|
+
*/
|
|
80
|
+
function outputError(error, details, opts) {
|
|
81
|
+
if (opts.json) {
|
|
82
|
+
console.log(JSON.stringify({ success: false, error, ...details }, null, 2));
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
console.error(`Error: ${error}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const policy = new commander_1.Command('policy')
|
|
89
|
+
.description('Policy file operations')
|
|
90
|
+
.option('--json', 'Output in machine-readable JSON format')
|
|
91
|
+
.option('--yes', 'Skip confirmation prompts (auto-confirm)')
|
|
92
|
+
.option('--strict', 'Exit non-zero on warnings');
|
|
51
93
|
exports.policy = policy;
|
|
52
94
|
/**
|
|
53
95
|
* peac policy init
|
|
@@ -58,31 +100,68 @@ policy
|
|
|
58
100
|
.command('init')
|
|
59
101
|
.description('Create a new PEAC policy file')
|
|
60
102
|
.option('-f, --format <format>', 'Output format (yaml or json)', 'yaml')
|
|
61
|
-
.option('-o, --output <file>', 'Output file path'
|
|
103
|
+
.option('-o, --output <file>', 'Output file path')
|
|
62
104
|
.option('--force', 'Overwrite existing file')
|
|
63
|
-
.
|
|
105
|
+
.option('--profile <id>', 'Use a pre-built profile as template')
|
|
106
|
+
.action((options, cmd) => {
|
|
107
|
+
const globalOpts = getGlobalOptions(cmd);
|
|
64
108
|
try {
|
|
65
109
|
const format = options.format?.toLowerCase() || 'yaml';
|
|
66
110
|
const outputPath = options.output || (format === 'json' ? 'peac-policy.json' : 'peac-policy.yaml');
|
|
67
|
-
// Check if file exists and --force not set
|
|
68
|
-
if (fs.existsSync(outputPath) && !options.force) {
|
|
69
|
-
|
|
70
|
-
console.error('Use --force to overwrite.');
|
|
111
|
+
// Check if file exists and --force/--yes not set
|
|
112
|
+
if (fs.existsSync(outputPath) && !options.force && !globalOpts.yes) {
|
|
113
|
+
outputError(`File already exists: ${outputPath}`, { path: outputPath, hint: 'Use --force or --yes to overwrite' }, globalOpts);
|
|
71
114
|
process.exit(1);
|
|
72
115
|
}
|
|
73
|
-
|
|
74
|
-
|
|
116
|
+
let content;
|
|
117
|
+
let policyName;
|
|
118
|
+
if (options.profile) {
|
|
119
|
+
// Use profile as template
|
|
120
|
+
try {
|
|
121
|
+
const profile = (0, policy_kit_1.loadProfile)(options.profile);
|
|
122
|
+
const policyDoc = profile.policy;
|
|
123
|
+
content =
|
|
124
|
+
format === 'json' ? (0, policy_kit_1.serializePolicyJson)(policyDoc) : (0, policy_kit_1.serializePolicyYaml)(policyDoc);
|
|
125
|
+
policyName = profile.name;
|
|
126
|
+
}
|
|
127
|
+
catch (err) {
|
|
128
|
+
if (err instanceof policy_kit_1.ProfileError) {
|
|
129
|
+
outputError(err.message, { code: err.code, profile: options.profile }, globalOpts);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
throw err;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
const example = (0, policy_kit_1.createExamplePolicy)();
|
|
137
|
+
content = format === 'json' ? (0, policy_kit_1.serializePolicyJson)(example) : (0, policy_kit_1.serializePolicyYaml)(example);
|
|
138
|
+
policyName = 'Example Policy';
|
|
139
|
+
}
|
|
75
140
|
fs.writeFileSync(outputPath, content, 'utf-8');
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
141
|
+
if (globalOpts.json) {
|
|
142
|
+
output({
|
|
143
|
+
success: true,
|
|
144
|
+
file: outputPath,
|
|
145
|
+
format,
|
|
146
|
+
profile: options.profile || null,
|
|
147
|
+
policyName,
|
|
148
|
+
}, globalOpts);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
console.log(`Created policy file: ${outputPath}`);
|
|
152
|
+
if (options.profile) {
|
|
153
|
+
console.log(`Based on profile: ${options.profile}`);
|
|
154
|
+
}
|
|
155
|
+
console.log('');
|
|
156
|
+
console.log('Next steps:');
|
|
157
|
+
console.log(' 1. Edit the policy file to define your access rules');
|
|
158
|
+
console.log(' 2. Validate with: peac policy validate ' + outputPath);
|
|
159
|
+
console.log(' 3. Generate artifacts with: peac policy generate ' + outputPath);
|
|
160
|
+
}
|
|
82
161
|
process.exit(0);
|
|
83
162
|
}
|
|
84
163
|
catch (err) {
|
|
85
|
-
|
|
164
|
+
outputError(err instanceof Error ? err.message : String(err), {}, globalOpts);
|
|
86
165
|
process.exit(1);
|
|
87
166
|
}
|
|
88
167
|
});
|
|
@@ -94,68 +173,123 @@ policy
|
|
|
94
173
|
.description('Validate a PEAC policy file (YAML or JSON)')
|
|
95
174
|
.argument('<file>', 'Path to policy file')
|
|
96
175
|
.option('-v, --verbose', 'Show detailed validation output')
|
|
97
|
-
.action((file, options) => {
|
|
176
|
+
.action((file, options, cmd) => {
|
|
177
|
+
const globalOpts = getGlobalOptions(cmd);
|
|
178
|
+
const warnings = [];
|
|
98
179
|
try {
|
|
99
|
-
console.log(`Validating policy file: ${file}\n`);
|
|
100
180
|
const policyDoc = (0, policy_kit_1.loadPolicy)(file);
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
|
|
181
|
+
// Collect any warnings (e.g., deprecated features)
|
|
182
|
+
// Currently no warnings defined, but this is the pattern for future use
|
|
183
|
+
const result = {
|
|
184
|
+
success: true,
|
|
185
|
+
file,
|
|
186
|
+
valid: true,
|
|
187
|
+
warnings,
|
|
188
|
+
policy: {
|
|
189
|
+
version: policyDoc.version,
|
|
190
|
+
name: policyDoc.name || null,
|
|
191
|
+
defaultDecision: policyDoc.defaults.decision,
|
|
192
|
+
ruleCount: policyDoc.rules.length,
|
|
193
|
+
rules: options.verbose
|
|
194
|
+
? policyDoc.rules.map((r) => ({
|
|
195
|
+
name: r.name,
|
|
196
|
+
decision: r.decision,
|
|
197
|
+
subject: r.subject || null,
|
|
198
|
+
purpose: r.purpose || null,
|
|
199
|
+
licensingMode: r.licensing_mode || null,
|
|
200
|
+
}))
|
|
201
|
+
: undefined,
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
if (globalOpts.json) {
|
|
205
|
+
output(result, globalOpts);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
console.log(`Validating policy file: ${file}\n`);
|
|
209
|
+
console.log('Policy is valid!\n');
|
|
210
|
+
console.log('Policy Information:');
|
|
211
|
+
console.log(` Version: ${policyDoc.version}`);
|
|
212
|
+
if (policyDoc.name) {
|
|
213
|
+
console.log(` Name: ${policyDoc.name}`);
|
|
214
|
+
}
|
|
215
|
+
console.log(` Default: ${policyDoc.defaults.decision}`);
|
|
216
|
+
console.log(` Rules: ${policyDoc.rules.length}`);
|
|
217
|
+
if (options.verbose && policyDoc.rules.length > 0) {
|
|
218
|
+
console.log('\nRules:');
|
|
219
|
+
for (const rule of policyDoc.rules) {
|
|
220
|
+
console.log(` - ${rule.name}: ${rule.decision}`);
|
|
221
|
+
if (rule.subject) {
|
|
222
|
+
const parts = [];
|
|
223
|
+
if (rule.subject.type) {
|
|
224
|
+
const types = Array.isArray(rule.subject.type)
|
|
225
|
+
? rule.subject.type.join('|')
|
|
226
|
+
: rule.subject.type;
|
|
227
|
+
parts.push(`type=${types}`);
|
|
228
|
+
}
|
|
229
|
+
if (rule.subject.labels) {
|
|
230
|
+
parts.push(`labels=[${rule.subject.labels.join(',')}]`);
|
|
231
|
+
}
|
|
232
|
+
if (rule.subject.id) {
|
|
233
|
+
parts.push(`id=${rule.subject.id}`);
|
|
234
|
+
}
|
|
235
|
+
if (parts.length > 0) {
|
|
236
|
+
console.log(` subject: ${parts.join(', ')}`);
|
|
237
|
+
}
|
|
123
238
|
}
|
|
124
|
-
if (rule.
|
|
125
|
-
|
|
239
|
+
if (rule.purpose) {
|
|
240
|
+
const purposes = Array.isArray(rule.purpose) ? rule.purpose.join('|') : rule.purpose;
|
|
241
|
+
console.log(` purpose: ${purposes}`);
|
|
126
242
|
}
|
|
127
|
-
if (
|
|
128
|
-
|
|
243
|
+
if (rule.licensing_mode) {
|
|
244
|
+
const modes = Array.isArray(rule.licensing_mode)
|
|
245
|
+
? rule.licensing_mode.join('|')
|
|
246
|
+
: rule.licensing_mode;
|
|
247
|
+
console.log(` licensing_mode: ${modes}`);
|
|
129
248
|
}
|
|
130
249
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
const modes = Array.isArray(rule.licensing_mode)
|
|
137
|
-
? rule.licensing_mode.join('|')
|
|
138
|
-
: rule.licensing_mode;
|
|
139
|
-
console.log(` licensing_mode: ${modes}`);
|
|
250
|
+
}
|
|
251
|
+
if (warnings.length > 0) {
|
|
252
|
+
console.log('\nWarnings:');
|
|
253
|
+
for (const warning of warnings) {
|
|
254
|
+
console.log(` - ${warning}`);
|
|
140
255
|
}
|
|
141
256
|
}
|
|
142
257
|
}
|
|
258
|
+
// Exit with non-zero if --strict and there are warnings
|
|
259
|
+
if (globalOpts.strict && warnings.length > 0) {
|
|
260
|
+
process.exit(1);
|
|
261
|
+
}
|
|
143
262
|
process.exit(0);
|
|
144
263
|
}
|
|
145
264
|
catch (err) {
|
|
146
265
|
if (err instanceof policy_kit_1.PolicyValidationError) {
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
266
|
+
const issues = err.issues.map((i) => ({
|
|
267
|
+
path: i.path.join('.'),
|
|
268
|
+
message: i.message,
|
|
269
|
+
}));
|
|
270
|
+
if (globalOpts.json) {
|
|
271
|
+
output({
|
|
272
|
+
success: false,
|
|
273
|
+
file,
|
|
274
|
+
valid: false,
|
|
275
|
+
error: 'Validation failed',
|
|
276
|
+
issues,
|
|
277
|
+
}, globalOpts);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
console.error('Policy validation failed:\n');
|
|
281
|
+
for (const issue of err.issues) {
|
|
282
|
+
console.error(` - ${issue.path.join('.')}: ${issue.message}`);
|
|
283
|
+
}
|
|
150
284
|
}
|
|
151
285
|
process.exit(1);
|
|
152
286
|
}
|
|
153
287
|
else if (err instanceof policy_kit_1.PolicyLoadError) {
|
|
154
|
-
|
|
288
|
+
outputError(`Failed to load policy: ${err.message}`, { file }, globalOpts);
|
|
155
289
|
process.exit(1);
|
|
156
290
|
}
|
|
157
291
|
else {
|
|
158
|
-
|
|
292
|
+
outputError(err instanceof Error ? err.message : String(err), {}, globalOpts);
|
|
159
293
|
process.exit(1);
|
|
160
294
|
}
|
|
161
295
|
}
|
|
@@ -173,7 +307,7 @@ policy
|
|
|
173
307
|
.command('generate')
|
|
174
308
|
.description('Generate deployment artifacts from a policy file')
|
|
175
309
|
.argument('<file>', 'Path to policy file')
|
|
176
|
-
.option('-o, --out <dir>', 'Output directory', 'dist')
|
|
310
|
+
.option('-o, --out <dir>', 'Output directory (use "-" for stdout)', 'dist')
|
|
177
311
|
.option('--well-known', 'Output peac.txt to .well-known/ subdirectory')
|
|
178
312
|
.option('--dry-run', 'Show what would be generated without writing files')
|
|
179
313
|
.option('--peac-version <version>', 'PEAC protocol version (default: 0.9)')
|
|
@@ -184,9 +318,13 @@ policy
|
|
|
184
318
|
.option('--rate-limit <limit>', 'Rate limit string (e.g., "100/hour", "unlimited")')
|
|
185
319
|
.option('--negotiate <url>', 'Negotiate endpoint URL')
|
|
186
320
|
.option('--no-comments', 'Omit comments from generated files')
|
|
187
|
-
.action((file, options) => {
|
|
321
|
+
.action((file, options, cmd) => {
|
|
322
|
+
const globalOpts = getGlobalOptions(cmd);
|
|
323
|
+
const isStdout = options.out === '-';
|
|
188
324
|
try {
|
|
189
|
-
|
|
325
|
+
if (!globalOpts.json && !isStdout) {
|
|
326
|
+
console.log(`Loading policy: ${file}\n`);
|
|
327
|
+
}
|
|
190
328
|
const policyDoc = (0, policy_kit_1.loadPolicy)(file);
|
|
191
329
|
const compileOptions = {
|
|
192
330
|
peacVersion: options.peacVersion,
|
|
@@ -198,6 +336,32 @@ policy
|
|
|
198
336
|
negotiateUrl: options.negotiate,
|
|
199
337
|
includeComments: options.comments !== false,
|
|
200
338
|
};
|
|
339
|
+
// Generate content
|
|
340
|
+
const peacTxt = (0, policy_kit_1.compilePeacTxt)(policyDoc, compileOptions);
|
|
341
|
+
const robotsTxt = (0, policy_kit_1.compileRobotsSnippet)(policyDoc, compileOptions);
|
|
342
|
+
const aiprefTemplates = (0, policy_kit_1.compileAiprefTemplates)(policyDoc, compileOptions);
|
|
343
|
+
const markdown = (0, policy_kit_1.renderPolicyMarkdown)(policyDoc, compileOptions);
|
|
344
|
+
// Stdout mode: output all content as JSON
|
|
345
|
+
if (isStdout || globalOpts.json) {
|
|
346
|
+
const result = {
|
|
347
|
+
success: true,
|
|
348
|
+
source: file,
|
|
349
|
+
artifacts: {
|
|
350
|
+
'peac.txt': peacTxt,
|
|
351
|
+
'robots-ai-snippet.txt': robotsTxt,
|
|
352
|
+
'aipref-headers.json': aiprefTemplates,
|
|
353
|
+
'ai-policy.md': markdown,
|
|
354
|
+
},
|
|
355
|
+
};
|
|
356
|
+
if (isStdout && !globalOpts.json) {
|
|
357
|
+
// Plain stdout: just output peac.txt
|
|
358
|
+
console.log(peacTxt);
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
output(result, { json: true });
|
|
362
|
+
}
|
|
363
|
+
process.exit(0);
|
|
364
|
+
}
|
|
201
365
|
// Determine output paths
|
|
202
366
|
const outDir = options.out;
|
|
203
367
|
let peacTxtPath;
|
|
@@ -210,11 +374,6 @@ policy
|
|
|
210
374
|
const robotsPath = path.join(outDir, 'robots-ai-snippet.txt');
|
|
211
375
|
const aiprefPath = path.join(outDir, 'aipref-headers.json');
|
|
212
376
|
const mdPath = path.join(outDir, 'ai-policy.md');
|
|
213
|
-
// Generate content
|
|
214
|
-
const peacTxt = (0, policy_kit_1.compilePeacTxt)(policyDoc, compileOptions);
|
|
215
|
-
const robotsTxt = (0, policy_kit_1.compileRobotsSnippet)(policyDoc, compileOptions);
|
|
216
|
-
const aiprefTemplates = (0, policy_kit_1.compileAiprefTemplates)(policyDoc, compileOptions);
|
|
217
|
-
const markdown = (0, policy_kit_1.renderPolicyMarkdown)(policyDoc, compileOptions);
|
|
218
377
|
if (options.dryRun) {
|
|
219
378
|
// Dry run: show what would be generated
|
|
220
379
|
console.log('Dry run - files that would be generated:\n');
|
|
@@ -262,11 +421,11 @@ policy
|
|
|
262
421
|
}
|
|
263
422
|
catch (err) {
|
|
264
423
|
if (err instanceof policy_kit_1.PolicyLoadError) {
|
|
265
|
-
|
|
424
|
+
outputError(`Failed to load policy: ${err.message}`, { file }, globalOpts);
|
|
266
425
|
process.exit(1);
|
|
267
426
|
}
|
|
268
427
|
else {
|
|
269
|
-
|
|
428
|
+
outputError(err instanceof Error ? err.message : String(err), {}, globalOpts);
|
|
270
429
|
process.exit(1);
|
|
271
430
|
}
|
|
272
431
|
}
|
|
@@ -286,7 +445,8 @@ policy
|
|
|
286
445
|
.option('-p, --purpose <purpose>', 'Access purpose (crawl, index, train, inference, ai_input, ai_index, search)')
|
|
287
446
|
.option('-m, --licensing-mode <mode>', 'Licensing mode (subscription, pay_per_crawl, pay_per_inference)')
|
|
288
447
|
.option('--all-matches', 'Show all matching rules, not just the first')
|
|
289
|
-
.action((file, options) => {
|
|
448
|
+
.action((file, options, cmd) => {
|
|
449
|
+
const globalOpts = getGlobalOptions(cmd);
|
|
290
450
|
try {
|
|
291
451
|
const policyDoc = (0, policy_kit_1.loadPolicy)(file);
|
|
292
452
|
// Build evaluation context from options
|
|
@@ -309,56 +469,244 @@ policy
|
|
|
309
469
|
if (options.licensingMode) {
|
|
310
470
|
context.licensing_mode = options.licensingMode;
|
|
311
471
|
}
|
|
312
|
-
console.log('Evaluation Context:');
|
|
313
|
-
if (context.subject) {
|
|
314
|
-
console.log(` Subject: ${JSON.stringify(context.subject)}`);
|
|
315
|
-
}
|
|
316
|
-
else {
|
|
317
|
-
console.log(' Subject: (any)');
|
|
318
|
-
}
|
|
319
|
-
console.log(` Purpose: ${context.purpose || '(any)'}`);
|
|
320
|
-
console.log(` Licensing Mode: ${context.licensing_mode || '(any)'}`);
|
|
321
|
-
console.log();
|
|
322
472
|
if (options.allMatches) {
|
|
323
473
|
const matches = (0, policy_kit_1.explainMatches)(policyDoc, context);
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
474
|
+
if (globalOpts.json) {
|
|
475
|
+
output({
|
|
476
|
+
success: true,
|
|
477
|
+
context,
|
|
478
|
+
matches: matches.map((m) => {
|
|
479
|
+
if (m === '[default]') {
|
|
480
|
+
return {
|
|
481
|
+
rule: '[default]',
|
|
482
|
+
decision: policyDoc.defaults.decision,
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
const rule = policyDoc.rules.find((r) => r.name === m);
|
|
486
|
+
return rule
|
|
487
|
+
? { rule: rule.name, decision: rule.decision }
|
|
488
|
+
: { rule: m, decision: null };
|
|
489
|
+
}),
|
|
490
|
+
}, globalOpts);
|
|
491
|
+
}
|
|
492
|
+
else {
|
|
493
|
+
console.log('Evaluation Context:');
|
|
494
|
+
if (context.subject) {
|
|
495
|
+
console.log(` Subject: ${JSON.stringify(context.subject)}`);
|
|
328
496
|
}
|
|
329
497
|
else {
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
498
|
+
console.log(' Subject: (any)');
|
|
499
|
+
}
|
|
500
|
+
console.log(` Purpose: ${context.purpose || '(any)'}`);
|
|
501
|
+
console.log(` Licensing Mode: ${context.licensing_mode || '(any)'}`);
|
|
502
|
+
console.log();
|
|
503
|
+
console.log(`Matching Rules (${matches.length}):`);
|
|
504
|
+
for (const match of matches) {
|
|
505
|
+
if (match === '[default]') {
|
|
506
|
+
console.log(` - [default] -> ${policyDoc.defaults.decision}`);
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
const rule = policyDoc.rules.find((r) => r.name === match);
|
|
510
|
+
if (rule) {
|
|
511
|
+
console.log(` - ${rule.name} -> ${rule.decision}`);
|
|
512
|
+
}
|
|
333
513
|
}
|
|
334
514
|
}
|
|
335
515
|
}
|
|
336
516
|
}
|
|
337
517
|
else {
|
|
338
518
|
const result = (0, policy_kit_1.evaluate)(policyDoc, context);
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
519
|
+
if (globalOpts.json) {
|
|
520
|
+
output({
|
|
521
|
+
success: true,
|
|
522
|
+
context,
|
|
523
|
+
result: {
|
|
524
|
+
decision: result.decision,
|
|
525
|
+
matchedRule: result.matched_rule || '[default]',
|
|
526
|
+
reason: result.reason || null,
|
|
527
|
+
},
|
|
528
|
+
}, globalOpts);
|
|
343
529
|
}
|
|
344
530
|
else {
|
|
345
|
-
console.log('
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
531
|
+
console.log('Evaluation Context:');
|
|
532
|
+
if (context.subject) {
|
|
533
|
+
console.log(` Subject: ${JSON.stringify(context.subject)}`);
|
|
534
|
+
}
|
|
535
|
+
else {
|
|
536
|
+
console.log(' Subject: (any)');
|
|
537
|
+
}
|
|
538
|
+
console.log(` Purpose: ${context.purpose || '(any)'}`);
|
|
539
|
+
console.log(` Licensing Mode: ${context.licensing_mode || '(any)'}`);
|
|
540
|
+
console.log();
|
|
541
|
+
console.log('Result:');
|
|
542
|
+
console.log(` Decision: ${result.decision}`);
|
|
543
|
+
if (result.matched_rule) {
|
|
544
|
+
console.log(` Matched Rule: ${result.matched_rule}`);
|
|
545
|
+
}
|
|
546
|
+
else {
|
|
547
|
+
console.log(' Matched Rule: (default)');
|
|
548
|
+
}
|
|
549
|
+
if (result.reason) {
|
|
550
|
+
console.log(` Reason: ${result.reason}`);
|
|
551
|
+
}
|
|
349
552
|
}
|
|
350
553
|
}
|
|
351
554
|
process.exit(0);
|
|
352
555
|
}
|
|
353
556
|
catch (err) {
|
|
354
557
|
if (err instanceof policy_kit_1.PolicyLoadError) {
|
|
355
|
-
|
|
558
|
+
outputError(`Failed to load policy: ${err.message}`, { file }, globalOpts);
|
|
356
559
|
process.exit(1);
|
|
357
560
|
}
|
|
358
561
|
else {
|
|
359
|
-
|
|
562
|
+
outputError(err instanceof Error ? err.message : String(err), {}, globalOpts);
|
|
563
|
+
process.exit(1);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
/**
|
|
568
|
+
* peac policy list-profiles
|
|
569
|
+
*
|
|
570
|
+
* List available pre-built policy profiles (v0.9.23+)
|
|
571
|
+
*/
|
|
572
|
+
policy
|
|
573
|
+
.command('list-profiles')
|
|
574
|
+
.description('List available pre-built policy profiles')
|
|
575
|
+
.action((options, cmd) => {
|
|
576
|
+
const globalOpts = getGlobalOptions(cmd);
|
|
577
|
+
try {
|
|
578
|
+
const profileIds = (0, policy_kit_1.listProfiles)();
|
|
579
|
+
const profiles = profileIds.map((id) => (0, policy_kit_1.getProfileSummary)(id));
|
|
580
|
+
if (globalOpts.json) {
|
|
581
|
+
output({
|
|
582
|
+
success: true,
|
|
583
|
+
profiles: profiles.map((p) => ({
|
|
584
|
+
id: p.id,
|
|
585
|
+
name: p.name,
|
|
586
|
+
description: p.description,
|
|
587
|
+
defaultDecision: p.defaultDecision,
|
|
588
|
+
ruleCount: p.ruleCount,
|
|
589
|
+
requiresReceipt: p.requiresReceipt,
|
|
590
|
+
requiredParams: p.requiredParams,
|
|
591
|
+
optionalParams: p.optionalParams,
|
|
592
|
+
})),
|
|
593
|
+
}, globalOpts);
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
console.log('Available Policy Profiles:\n');
|
|
597
|
+
for (const profile of profiles) {
|
|
598
|
+
console.log(` ${profile.id}`);
|
|
599
|
+
console.log(` Name: ${profile.name}`);
|
|
600
|
+
console.log(` Default: ${profile.defaultDecision}`);
|
|
601
|
+
console.log(` Rules: ${profile.ruleCount}`);
|
|
602
|
+
if (profile.requiresReceipt) {
|
|
603
|
+
console.log(' Requires receipt: yes');
|
|
604
|
+
}
|
|
605
|
+
if (profile.requiredParams.length > 0) {
|
|
606
|
+
console.log(` Required params: ${profile.requiredParams.join(', ')}`);
|
|
607
|
+
}
|
|
608
|
+
console.log();
|
|
609
|
+
}
|
|
610
|
+
console.log('Use "peac policy show-profile <id>" for full details');
|
|
611
|
+
console.log('Use "peac policy init --profile <id>" to create a policy from a profile');
|
|
612
|
+
}
|
|
613
|
+
process.exit(0);
|
|
614
|
+
}
|
|
615
|
+
catch (err) {
|
|
616
|
+
outputError(err instanceof Error ? err.message : String(err), {}, globalOpts);
|
|
617
|
+
process.exit(1);
|
|
618
|
+
}
|
|
619
|
+
});
|
|
620
|
+
/**
|
|
621
|
+
* peac policy show-profile <id>
|
|
622
|
+
*
|
|
623
|
+
* Show details of a specific profile (v0.9.23+)
|
|
624
|
+
*/
|
|
625
|
+
policy
|
|
626
|
+
.command('show-profile')
|
|
627
|
+
.description('Show details of a specific policy profile')
|
|
628
|
+
.argument('<id>', 'Profile ID')
|
|
629
|
+
.action((id, options, cmd) => {
|
|
630
|
+
const globalOpts = getGlobalOptions(cmd);
|
|
631
|
+
try {
|
|
632
|
+
const profile = (0, policy_kit_1.loadProfile)(id);
|
|
633
|
+
const summary = (0, policy_kit_1.getProfileSummary)(id);
|
|
634
|
+
if (globalOpts.json) {
|
|
635
|
+
output({
|
|
636
|
+
success: true,
|
|
637
|
+
profile: {
|
|
638
|
+
id: profile.id,
|
|
639
|
+
name: profile.name,
|
|
640
|
+
description: profile.description,
|
|
641
|
+
policy: profile.policy,
|
|
642
|
+
parameters: profile.parameters,
|
|
643
|
+
defaults: profile.defaults,
|
|
644
|
+
},
|
|
645
|
+
}, globalOpts);
|
|
646
|
+
}
|
|
647
|
+
else {
|
|
648
|
+
console.log(`Profile: ${profile.name}`);
|
|
649
|
+
console.log(`ID: ${profile.id}`);
|
|
650
|
+
console.log();
|
|
651
|
+
console.log('Description:');
|
|
652
|
+
console.log(profile.description
|
|
653
|
+
.split('\n')
|
|
654
|
+
.map((l) => ` ${l}`)
|
|
655
|
+
.join('\n'));
|
|
656
|
+
console.log();
|
|
657
|
+
console.log('Policy:');
|
|
658
|
+
console.log(` Version: ${profile.policy.version}`);
|
|
659
|
+
console.log(` Default decision: ${profile.policy.defaults.decision}`);
|
|
660
|
+
console.log(` Rules: ${profile.policy.rules?.length || 0}`);
|
|
661
|
+
if (profile.policy.rules && profile.policy.rules.length > 0) {
|
|
662
|
+
console.log();
|
|
663
|
+
console.log('Rules:');
|
|
664
|
+
for (const rule of profile.policy.rules) {
|
|
665
|
+
console.log(` - ${rule.name}: ${rule.decision}`);
|
|
666
|
+
if (rule.purpose) {
|
|
667
|
+
const purposes = Array.isArray(rule.purpose) ? rule.purpose.join(', ') : rule.purpose;
|
|
668
|
+
console.log(` purpose: ${purposes}`);
|
|
669
|
+
}
|
|
670
|
+
if (rule.reason) {
|
|
671
|
+
console.log(` reason: ${rule.reason}`);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
if (Object.keys(profile.parameters || {}).length > 0) {
|
|
676
|
+
console.log();
|
|
677
|
+
console.log('Parameters:');
|
|
678
|
+
for (const [key, param] of Object.entries(profile.parameters || {})) {
|
|
679
|
+
const required = param.required ? ' (required)' : '';
|
|
680
|
+
console.log(` ${key}${required}`);
|
|
681
|
+
console.log(` ${param.description}`);
|
|
682
|
+
if (param.default) {
|
|
683
|
+
console.log(` Default: ${param.default}`);
|
|
684
|
+
}
|
|
685
|
+
if (param.example) {
|
|
686
|
+
console.log(` Example: ${param.example}`);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
if (profile.defaults) {
|
|
691
|
+
console.log();
|
|
692
|
+
console.log('Defaults:');
|
|
693
|
+
if (profile.defaults.requirements?.receipt) {
|
|
694
|
+
console.log(' Receipt required: yes');
|
|
695
|
+
}
|
|
696
|
+
if (profile.defaults.rate_limit) {
|
|
697
|
+
console.log(` Rate limit: ${profile.defaults.rate_limit.limit}/${profile.defaults.rate_limit.window_seconds}s`);
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
process.exit(0);
|
|
702
|
+
}
|
|
703
|
+
catch (err) {
|
|
704
|
+
if (err instanceof policy_kit_1.ProfileError) {
|
|
705
|
+
outputError(err.message, { code: err.code, profile: id }, globalOpts);
|
|
360
706
|
process.exit(1);
|
|
361
707
|
}
|
|
708
|
+
outputError(err instanceof Error ? err.message : String(err), {}, globalOpts);
|
|
709
|
+
process.exit(1);
|
|
362
710
|
}
|
|
363
711
|
});
|
|
364
712
|
//# sourceMappingURL=policy.js.map
|