@ai-dossier/cli 0.4.1 → 0.4.2

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.
Files changed (103) hide show
  1. package/README.md +30 -25
  2. package/bin/dossier-verify +6 -440
  3. package/dist/cli.js +80 -21
  4. package/dist/cli.js.map +1 -1
  5. package/dist/commands/cache.d.ts.map +1 -1
  6. package/dist/commands/cache.js.map +1 -1
  7. package/dist/commands/checksum.js.map +1 -1
  8. package/dist/commands/commands.d.ts.map +1 -1
  9. package/dist/commands/commands.js +4 -2
  10. package/dist/commands/commands.js.map +1 -1
  11. package/dist/commands/config-cmd.d.ts.map +1 -1
  12. package/dist/commands/config-cmd.js +170 -7
  13. package/dist/commands/config-cmd.js.map +1 -1
  14. package/dist/commands/create.d.ts.map +1 -1
  15. package/dist/commands/create.js +19 -8
  16. package/dist/commands/create.js.map +1 -1
  17. package/dist/commands/export.d.ts.map +1 -1
  18. package/dist/commands/export.js +15 -5
  19. package/dist/commands/export.js.map +1 -1
  20. package/dist/commands/format.d.ts.map +1 -1
  21. package/dist/commands/format.js.map +1 -1
  22. package/dist/commands/get.d.ts.map +1 -1
  23. package/dist/commands/get.js +19 -6
  24. package/dist/commands/get.js.map +1 -1
  25. package/dist/commands/info.d.ts.map +1 -1
  26. package/dist/commands/info.js +20 -6
  27. package/dist/commands/info.js.map +1 -1
  28. package/dist/commands/install-skill.d.ts.map +1 -1
  29. package/dist/commands/install-skill.js +16 -9
  30. package/dist/commands/install-skill.js.map +1 -1
  31. package/dist/commands/lint.d.ts.map +1 -1
  32. package/dist/commands/lint.js.map +1 -1
  33. package/dist/commands/list.d.ts.map +1 -1
  34. package/dist/commands/list.js +54 -41
  35. package/dist/commands/list.js.map +1 -1
  36. package/dist/commands/login.d.ts.map +1 -1
  37. package/dist/commands/login.js +25 -5
  38. package/dist/commands/login.js.map +1 -1
  39. package/dist/commands/logout.d.ts.map +1 -1
  40. package/dist/commands/logout.js +22 -5
  41. package/dist/commands/logout.js.map +1 -1
  42. package/dist/commands/prompt-hook.d.ts.map +1 -1
  43. package/dist/commands/prompt-hook.js +4 -13
  44. package/dist/commands/prompt-hook.js.map +1 -1
  45. package/dist/commands/publish.d.ts.map +1 -1
  46. package/dist/commands/publish.js +35 -22
  47. package/dist/commands/publish.js.map +1 -1
  48. package/dist/commands/pull.d.ts.map +1 -1
  49. package/dist/commands/pull.js +23 -8
  50. package/dist/commands/pull.js.map +1 -1
  51. package/dist/commands/remove.d.ts.map +1 -1
  52. package/dist/commands/remove.js +25 -12
  53. package/dist/commands/remove.js.map +1 -1
  54. package/dist/commands/reset-hooks.js +1 -1
  55. package/dist/commands/reset-hooks.js.map +1 -1
  56. package/dist/commands/run.d.ts.map +1 -1
  57. package/dist/commands/run.js +75 -48
  58. package/dist/commands/run.js.map +1 -1
  59. package/dist/commands/search.d.ts.map +1 -1
  60. package/dist/commands/search.js +29 -27
  61. package/dist/commands/search.js.map +1 -1
  62. package/dist/commands/sign.js.map +1 -1
  63. package/dist/commands/skill-export.d.ts +3 -0
  64. package/dist/commands/skill-export.d.ts.map +1 -0
  65. package/dist/commands/skill-export.js +218 -0
  66. package/dist/commands/skill-export.js.map +1 -0
  67. package/dist/commands/validate.d.ts.map +1 -1
  68. package/dist/commands/validate.js.map +1 -1
  69. package/dist/commands/verify.d.ts.map +1 -1
  70. package/dist/commands/verify.js +1 -8
  71. package/dist/commands/verify.js.map +1 -1
  72. package/dist/commands/whoami.d.ts.map +1 -1
  73. package/dist/commands/whoami.js +108 -25
  74. package/dist/commands/whoami.js.map +1 -1
  75. package/dist/config.d.ts +38 -1
  76. package/dist/config.d.ts.map +1 -1
  77. package/dist/config.js +128 -1
  78. package/dist/config.js.map +1 -1
  79. package/dist/credentials.d.ts +14 -9
  80. package/dist/credentials.d.ts.map +1 -1
  81. package/dist/credentials.js +119 -49
  82. package/dist/credentials.js.map +1 -1
  83. package/dist/help.d.ts +7 -0
  84. package/dist/help.d.ts.map +1 -0
  85. package/dist/help.js +86 -0
  86. package/dist/help.js.map +1 -0
  87. package/dist/helpers.d.ts +2 -10
  88. package/dist/helpers.d.ts.map +1 -1
  89. package/dist/helpers.js +10 -28
  90. package/dist/helpers.js.map +1 -1
  91. package/dist/multi-registry.d.ts +71 -0
  92. package/dist/multi-registry.d.ts.map +1 -0
  93. package/dist/multi-registry.js +136 -0
  94. package/dist/multi-registry.js.map +1 -0
  95. package/dist/registry-client.d.ts +64 -8
  96. package/dist/registry-client.d.ts.map +1 -1
  97. package/dist/registry-client.js +13 -0
  98. package/dist/registry-client.js.map +1 -1
  99. package/dist/verify-dossier.d.ts +28 -0
  100. package/dist/verify-dossier.d.ts.map +1 -0
  101. package/dist/verify-dossier.js +329 -0
  102. package/dist/verify-dossier.js.map +1 -0
  103. package/package.json +1 -1
package/README.md CHANGED
@@ -36,8 +36,8 @@ cd cli
36
36
  npm link # Links the CLI globally for development
37
37
 
38
38
  # Or use directly
39
- chmod +x bin/dossier-verify
40
- ./bin/dossier-verify <file-or-url>
39
+ chmod +x bin/ai-dossier
40
+ ./bin/ai-dossier verify <file-or-url>
41
41
  ```
42
42
 
43
43
  ---
@@ -74,10 +74,10 @@ Commands that require confirmation (`publish`, `remove`, `cache clean`) will fai
74
74
 
75
75
  ```bash
76
76
  # Verify local file
77
- dossier-verify path/to/dossier.ds.md
77
+ ai-dossier verify path/to/dossier.ds.md
78
78
 
79
79
  # Verify remote dossier
80
- dossier-verify https://example.com/dossier.ds.md
80
+ ai-dossier verify https://example.com/dossier.ds.md
81
81
  ```
82
82
 
83
83
  **Exit codes**:
@@ -88,7 +88,7 @@ dossier-verify https://example.com/dossier.ds.md
88
88
  ### Verbose Mode
89
89
 
90
90
  ```bash
91
- dossier-verify --verbose path/to/dossier.ds.md
91
+ ai-dossier verify --verbose path/to/dossier.ds.md
92
92
  ```
93
93
 
94
94
  Shows:
@@ -103,7 +103,7 @@ Shows:
103
103
  ```bash
104
104
  # Shell function wrapper
105
105
  claude-run-dossier() {
106
- if dossier-verify "$1"; then
106
+ if ai-dossier verify "$1"; then
107
107
  claude-code "The dossier at $1 has been verified. Please execute it."
108
108
  else
109
109
  echo "❌ Security verification failed. Not executing."
@@ -117,7 +117,7 @@ claude-run-dossier https://example.com/dossier.ds.md
117
117
  **Cursor**:
118
118
  ```bash
119
119
  cursor-run-dossier() {
120
- if dossier-verify "$1"; then
120
+ if ai-dossier verify "$1"; then
121
121
  cursor "Execute the verified dossier at $1"
122
122
  else
123
123
  echo "❌ Verification failed"
@@ -132,7 +132,7 @@ safe-run-dossier() {
132
132
  local url="$1"
133
133
  local tool="${2:-claude-code}"
134
134
 
135
- if dossier-verify "$url"; then
135
+ if ai-dossier verify "$url"; then
136
136
  echo "✅ Dossier verified. Passing to $tool..."
137
137
  "$tool" "run $url"
138
138
  else
@@ -199,7 +199,7 @@ safe-run-dossier https://example.com/dossier.ds.md cursor
199
199
  ### Example 1: Legitimate Dossier (Passes)
200
200
 
201
201
  ```bash
202
- $ dossier-verify examples/data-science/train-ml-model.ds.md
202
+ $ ai-dossier verify examples/data-science/train-ml-model.ds.md
203
203
 
204
204
  🔐 Dossier Verification Tool
205
205
 
@@ -228,7 +228,7 @@ $ echo $?
228
228
  ### Example 2: Malicious Dossier (Blocked)
229
229
 
230
230
  ```bash
231
- $ dossier-verify https://raw.githubusercontent.com/imboard-ai/ai-dossier/main/examples/security/validate-project-config.ds.md
231
+ $ ai-dossier verify https://raw.githubusercontent.com/imboard-ai/ai-dossier/main/examples/security/validate-project-config.ds.md
232
232
 
233
233
  🔐 Dossier Verification Tool
234
234
 
@@ -268,7 +268,7 @@ $ echo $?
268
268
  # Wrapper function for Claude Code
269
269
  claude-run-dossier() {
270
270
  echo "Verifying dossier security..."
271
- if ~/projects/dossier/cli/bin/dossier-verify "$1"; then
271
+ if ai-dossier verify "$1"; then
272
272
  echo ""
273
273
  echo "✅ Verification passed. Executing with Claude Code..."
274
274
  claude-code "Execute the verified dossier at $1"
@@ -292,7 +292,7 @@ claude-run-dossier https://example.com/dossier.ds.md
292
292
 
293
293
  ```
294
294
  User Command:
295
- dossier-verify https://example.com/dossier.ds.md
295
+ ai-dossier verify https://example.com/dossier.ds.md
296
296
 
297
297
  Download/Read File
298
298
 
@@ -357,23 +357,28 @@ Exit 0 (safe) or 1 (unsafe)
357
357
 
358
358
  ## Roadmap
359
359
 
360
- ### v0.1.0 (Current)
360
+ ### v0.1.0
361
361
  - ✅ Basic checksum verification
362
362
  - ✅ Signature presence detection
363
363
  - ✅ Exit code support
364
364
  - ✅ URL download support
365
365
 
366
- ### v0.2.0 (Next)
367
- - Full minisign signature verification
368
- - Trusted keys management (~/.dossier/trusted-keys.txt)
369
- - --run flag implementation
370
- - ⏳ Better error messages
366
+ ### v0.2.0
367
+ - Multi-command CLI structure (`ai-dossier <command>`)
368
+ - `dossier run` command with 5-stage verification pipeline
369
+ - LLM auto-detection and execution integration
371
370
 
372
- ### v0.3.0 (Future)
373
- - Interactive trust prompts
374
- - Key import/export
375
- - Signature verification caching
376
- - JSON output mode (for tooling)
371
+ ### v0.3.0
372
+ - Modular TypeScript migration
373
+ - Comprehensive test suite (261+ tests)
374
+ - CLI parity with dossier-tools
375
+ - `@ai-dossier` npm scope and CI/CD publishing
376
+
377
+ ### v0.4.0 (Current)
378
+ - ✅ Unified dossier parser across core/cli/mcp
379
+ - ✅ JSON output mode (`--json` flag on commands)
380
+ - ✅ Registry integration (publish, remove, install-skill)
381
+ - ✅ Non-TTY stdin detection
377
382
 
378
383
  ### v1.0.0 (Stable)
379
384
  - ⏳ Complete signature verification
@@ -392,10 +397,10 @@ cd cli
392
397
  npm link # For local testing
393
398
 
394
399
  # Test
395
- dossier-verify ../examples/devops/deploy-to-aws.ds.md
400
+ ai-dossier verify ../examples/devops/deploy-to-aws.ds.md
396
401
 
397
402
  # Test with malicious example
398
- dossier-verify ../examples/security/validate-project-config.ds.md
403
+ ai-dossier verify ../examples/security/validate-project-config.ds.md
399
404
  ```
400
405
 
401
406
  ### Adding Features
@@ -1,443 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- /**
4
- * Dossier Verification CLI
5
- *
6
- * Enforces security verification of dossier files before execution.
7
- * Provides command-line interface for checksum and signature validation.
8
- *
9
- * Usage:
10
- * dossier-verify <file-or-url>
11
- * dossier-verify --run <file-or-url>
12
- * dossier-verify --verbose <file-or-url>
13
- */
3
+ // Thin shim — all logic lives in src/verify-dossier.ts
4
+ const { main } = require('../dist/verify-dossier');
14
5
 
15
- const fs = require('fs');
16
- const path = require('path');
17
- const crypto = require('crypto');
18
- const https = require('https');
19
- const http = require('http');
20
- const { execSync } = require('child_process');
21
- const {
22
- parseDossierContent,
23
- verifyIntegrity,
24
- loadTrustedKeys,
25
- verifySignature
26
- } = require('@ai-dossier/core');
27
- const { convertGitHubBlobToRaw } = require('../dist/github-url');
28
-
29
- // Colors for terminal output
30
- const colors = {
31
- reset: '\x1b[0m',
32
- bright: '\x1b[1m',
33
- red: '\x1b[31m',
34
- green: '\x1b[32m',
35
- yellow: '\x1b[33m',
36
- blue: '\x1b[34m',
37
- cyan: '\x1b[36m',
38
- };
39
-
40
- function log(message, color = 'reset') {
41
- console.log(`${colors[color]}${message}${colors.reset}`);
42
- }
43
-
44
- function error(message) {
45
- log(`\u274C ${message}`, 'red');
46
- }
47
-
48
- function success(message) {
49
- log(`\u2705 ${message}`, 'green');
50
- }
51
-
52
- function warning(message) {
53
- log(`\u26A0\uFE0F ${message}`, 'yellow');
54
- }
55
-
56
- function info(message) {
57
- log(`\u2139\uFE0F ${message}`, 'cyan');
58
- }
59
-
60
- // Parse command line arguments
61
- function parseArgs() {
62
- const args = process.argv.slice(2);
63
- const options = {
64
- verbose: false,
65
- run: false,
66
- outputPath: false,
67
- help: false,
68
- input: null,
69
- };
70
-
71
- for (let i = 0; i < args.length; i++) {
72
- const arg = args[i];
73
- if (arg === '--verbose' || arg === '-v') {
74
- options.verbose = true;
75
- } else if (arg === '--run') {
76
- options.run = true;
77
- } else if (arg === '--output-path') {
78
- options.outputPath = true;
79
- } else if (arg === '--help' || arg === '-h') {
80
- options.help = true;
81
- } else if (!options.input) {
82
- options.input = arg;
83
- }
84
- }
85
-
86
- return options;
87
- }
88
-
89
- function showHelp() {
90
- console.log(`
91
- ${colors.bright}Dossier Verification CLI${colors.reset}
92
-
93
- ${colors.bright}Usage:${colors.reset}
94
- dossier-verify <file-or-url> Verify dossier security
95
- dossier-verify --run <file-or-url> Verify and execute if safe
96
- dossier-verify --verbose <file-or-url> Show detailed verification
97
- dossier-verify --output-path <url> Download and output path
98
- dossier-verify --help Show this help
99
-
100
- ${colors.bright}Exit Codes:${colors.reset}
101
- 0 - Verification passed (safe to execute)
102
- 1 - Verification failed (do not execute)
103
- 2 - Error occurred (cannot verify)
104
-
105
- ${colors.bright}Examples:${colors.reset}
106
- # Verify local file
107
- dossier-verify path/to/dossier.ds.md
108
-
109
- # Verify remote dossier
110
- dossier-verify https://example.com/dossier.ds.md
111
-
112
- # Verify and run if safe
113
- dossier-verify --run https://example.com/dossier.ds.md
114
-
115
- # Use in shell script
116
- if dossier-verify "$URL"; then
117
- claude-code "run $URL"
118
- else
119
- echo "Security verification failed"
120
- fi
121
-
122
- ${colors.bright}Security Checks:${colors.reset}
123
- \u2713 SHA256 checksum verification (required)
124
- \u2713 Signature verification (if present)
125
- \u2713 Trusted keys check
126
- \u2713 Risk level assessment
127
-
128
- ${colors.bright}More Information:${colors.reset}
129
- Documentation: https://github.com/imboard/ai-dossier
130
- Security: SECURITY_STATUS.md
131
- Protocol: PROTOCOL.md
132
- `);
133
- }
134
-
135
- // Download file from URL
136
- async function downloadFile(url) {
137
- // Convert GitHub blob URLs to raw URLs
138
- const resolvedUrl = convertGitHubBlobToRaw(url);
139
-
140
- return new Promise((resolve, reject) => {
141
- const protocol = resolvedUrl.startsWith('https://') ? https : http;
142
-
143
- protocol.get(resolvedUrl, (res) => {
144
- if (res.statusCode === 301 || res.statusCode === 302) {
145
- // Follow redirect
146
- return downloadFile(res.headers.location).then(resolve).catch(reject);
147
- }
148
-
149
- if (res.statusCode !== 200) {
150
- return reject(new Error(`HTTP ${res.statusCode}: ${res.statusMessage}`));
151
- }
152
-
153
- let data = '';
154
- res.on('data', (chunk) => { data += chunk; });
155
- res.on('end', () => resolve(data));
156
- }).on('error', reject);
157
- });
158
- }
159
-
160
- // Parse dossier frontmatter (using @ai-dossier/core)
161
- function parseDossier(content) {
162
- const parsed = parseDossierContent(content);
163
- return {
164
- frontmatter: parsed.frontmatter,
165
- body: parsed.body
166
- };
167
- }
168
-
169
- // Verify checksum (using @ai-dossier/core)
170
- function verifyChecksum(body, declaredHash) {
171
- const result = verifyIntegrity(body, declaredHash);
172
- return {
173
- passed: result.status === 'valid',
174
- declared: result.expectedHash,
175
- actual: result.actualHash,
176
- };
177
- }
178
-
179
- // Verify signature (using @ai-dossier/core for real cryptographic verification)
180
- async function checkSignature(body, frontmatter) {
181
- if (!frontmatter.signature) {
182
- return {
183
- present: false,
184
- verified: false,
185
- trusted: false,
186
- message: 'No signature present',
187
- };
188
- }
189
-
190
- const signature = frontmatter.signature;
191
- const trustedKeys = loadTrustedKeys();
192
- // Check both key_id and public_key for trusted status
193
- // key_id is easier to manage in trusted-keys.txt file
194
- const isTrusted = trustedKeys.has(signature.key_id) || trustedKeys.has(signature.public_key);
195
-
196
- const result = await verifySignature(body, signature);
197
-
198
- if (result.valid) {
199
- return {
200
- present: true,
201
- verified: true,
202
- trusted: isTrusted,
203
- message: isTrusted
204
- ? `Verified signature from trusted source: ${trustedKeys.get(signature.key_id) || trustedKeys.get(signature.public_key)}`
205
- : 'Valid signature but key is not in trusted list',
206
- };
207
- }
208
-
209
- if (result.error) {
210
- return {
211
- present: true,
212
- verified: false,
213
- trusted: false,
214
- message: `Verification error: ${result.error}`,
215
- };
216
- }
217
-
218
- return {
219
- present: true,
220
- verified: false,
221
- trusted: isTrusted,
222
- message: 'Signature verification FAILED',
223
- };
224
- }
225
-
226
- // Assess risk
227
- function assessRisk(frontmatter, checksumResult, signatureResult) {
228
- const issues = [];
229
- let riskLevel = 'low';
230
- let shouldBlock = false;
231
-
232
- // Checksum failure is critical
233
- if (!checksumResult.passed) {
234
- issues.push('Checksum verification FAILED - content has been tampered with');
235
- riskLevel = 'critical';
236
- shouldBlock = true;
237
- }
238
-
239
- // Signature issues
240
- if (signatureResult.present && !signatureResult.verified) {
241
- issues.push('Signature verification FAILED or could not be verified');
242
- if (riskLevel !== 'critical') riskLevel = 'high';
243
- shouldBlock = true;
244
- }
245
-
246
- // Valid signature but not trusted - BLOCK execution
247
- if (signatureResult.present && signatureResult.verified && !signatureResult.trusted) {
248
- issues.push('Signature is valid but signer is not in your trusted keys list');
249
- issues.push('Add the public key to ~/.dossier/trusted-keys.txt to trust this signer');
250
- if (riskLevel === 'low') riskLevel = 'medium';
251
- shouldBlock = true;
252
- }
253
-
254
- // No signature on high-risk dossier
255
- if (!signatureResult.present && frontmatter.risk_level === 'high') {
256
- issues.push('High-risk dossier without signature');
257
- if (riskLevel === 'low') riskLevel = 'medium';
258
- }
259
-
260
- if (!signatureResult.present && frontmatter.risk_level === 'critical') {
261
- issues.push('Critical-risk dossier without signature');
262
- if (riskLevel !== 'critical') riskLevel = 'high';
263
- }
264
-
265
- return {
266
- level: riskLevel,
267
- issues,
268
- recommendation: shouldBlock ? 'BLOCK' : 'ALLOW',
269
- };
270
- }
271
-
272
- // Main verification function
273
- async function verifyDossier(input, options) {
274
- try {
275
- log(`\n${colors.bright}\uD83D\uDD10 Dossier Verification Tool${colors.reset}\n`);
276
-
277
- // Determine if input is URL or file
278
- const isUrl = input.startsWith('http://') || input.startsWith('https://');
279
- let content;
280
- let displayPath = input;
281
-
282
- if (isUrl) {
283
- info(`Downloading: ${input}`);
284
- content = await downloadFile(input);
285
- success('Downloaded successfully');
286
- } else {
287
- info(`Reading: ${input}`);
288
- content = fs.readFileSync(input, 'utf8');
289
- displayPath = path.resolve(input);
290
- success('File read successfully');
291
- }
292
-
293
- // Parse dossier
294
- info('Parsing dossier...');
295
- const { frontmatter, body } = parseDossier(content);
296
- success(`Parsed: ${frontmatter.title} v${frontmatter.version}`);
297
-
298
- if (options.verbose) {
299
- console.log(`\n${colors.bright}Dossier Metadata:${colors.reset}`);
300
- console.log(` Title: ${frontmatter.title}`);
301
- console.log(` Version: ${frontmatter.version}`);
302
- console.log(` Risk Level: ${frontmatter.risk_level}`);
303
- console.log(` Protocol: ${frontmatter.protocol_version}`);
304
- }
305
-
306
- // Verify checksum
307
- console.log(`\n${colors.bright}\uD83D\uDCCA Integrity Check:${colors.reset}`);
308
- const checksumResult = verifyChecksum(body, frontmatter.checksum?.hash);
309
-
310
- if (checksumResult.passed) {
311
- success('Checksum VALID - content has not been tampered with');
312
- if (options.verbose) {
313
- console.log(` Hash: ${checksumResult.actual}`);
314
- }
315
- } else {
316
- error('Checksum INVALID - content has been modified!');
317
- if (options.verbose) {
318
- console.log(` Declared: ${checksumResult.declared}`);
319
- console.log(` Actual: ${checksumResult.actual}`);
320
- }
321
- }
322
-
323
- // Verify signature
324
- console.log(`\n${colors.bright}\uD83D\uDD0F Authenticity Check:${colors.reset}`);
325
- const signatureResult = await checkSignature(body, frontmatter);
326
-
327
- if (signatureResult.present) {
328
- if (signatureResult.verified && signatureResult.trusted) {
329
- success('Signature VERIFIED - from trusted author');
330
- } else if (signatureResult.verified && !signatureResult.trusted) {
331
- warning(signatureResult.message);
332
- if (frontmatter.signature?.signed_by) {
333
- console.log(` Signed by: ${frontmatter.signature.signed_by}`);
334
- }
335
- console.log(`\n ${colors.cyan}To trust this signer, run:${colors.reset}`);
336
- const publicKey = frontmatter.signature.public_key || frontmatter.signature.key_id;
337
- const identifier = frontmatter.signature.signed_by
338
- ? frontmatter.signature.signed_by.split('<')[0].trim().toLowerCase().replace(/\s+/g, '-')
339
- : 'unknown-signer';
340
- console.log(` ${colors.bright}dossier keys add "${publicKey}" "${identifier}"${colors.reset}\n`);
341
- } else {
342
- warning(signatureResult.message);
343
- if (frontmatter.signature?.signed_by) {
344
- console.log(` Signed by: ${frontmatter.signature.signed_by}`);
345
- }
346
- }
347
- } else {
348
- warning('No signature present (dossier is unsigned)');
349
- }
350
-
351
- // Assess risk
352
- console.log(`\n${colors.bright}\uD83D\uDD34 Risk Assessment:${colors.reset}`);
353
- const risk = assessRisk(frontmatter, checksumResult, signatureResult);
354
-
355
- const riskColors = {
356
- low: 'green',
357
- medium: 'yellow',
358
- high: 'yellow',
359
- critical: 'red',
360
- };
361
-
362
- log(` Risk Level: ${risk.level.toUpperCase()}`, riskColors[risk.level]);
363
-
364
- if (risk.issues.length > 0) {
365
- console.log(`\n Issues Found:`);
366
- risk.issues.forEach(issue => {
367
- console.log(` - ${issue}`);
368
- });
369
- }
370
-
371
- // Recommendation
372
- console.log(`\n${colors.bright}Recommendation:${colors.reset}`, risk.recommendation);
373
-
374
- if (risk.recommendation === 'BLOCK') {
375
- error('\nDO NOT EXECUTE this dossier');
376
- console.log(' Security verification failed.');
377
- console.log(' This dossier may have been tampered with or is from an untrusted source.\n');
378
- return false;
379
- } else if (risk.level === 'medium' || risk.level === 'high') {
380
- warning('\nProceed with CAUTION');
381
- console.log(' Review the dossier code before executing.');
382
- console.log(' Consider the risk level and your trust in the source.\n');
383
- return true;
384
- } else {
385
- success('\nSafe to execute');
386
- console.log(' Dossier passed security verification.\n');
387
- return true;
388
- }
389
-
390
- } catch (err) {
391
- error(`\nVerification failed: ${err.message}`);
392
- if (options.verbose) {
393
- console.error(err);
394
- }
395
- return false;
396
- }
397
- }
398
-
399
- // Main entry point
400
- async function main() {
401
- const options = parseArgs();
402
-
403
- if (options.help || !options.input) {
404
- showHelp();
405
- process.exit(options.help ? 0 : 2);
406
- }
407
-
408
- const passed = await verifyDossier(options.input, options);
409
-
410
- if (!passed) {
411
- process.exit(1); // Verification failed
412
- }
413
-
414
- if (options.run) {
415
- warning('\n--run flag not yet implemented');
416
- warning('For now, manually execute the dossier if verification passed');
417
- }
418
-
419
- if (options.outputPath) {
420
- // Would output the path to downloaded file
421
- warning('\n--output-path flag not yet implemented');
422
- }
423
-
424
- process.exit(0); // Success
425
- }
426
-
427
- // Run if called directly
428
- if (require.main === module) {
429
- main().catch(err => {
430
- error(`Fatal error: ${err.message}`);
431
- process.exit(2);
432
- });
433
- }
434
-
435
- module.exports = {
436
- verifyDossier,
437
- parseDossier,
438
- verifyChecksum,
439
- assessRisk,
440
- checkSignature,
441
- parseArgs,
442
- downloadFile,
443
- };
6
+ main().catch((err) => {
7
+ console.error(`Fatal error: ${err.message}`);
8
+ process.exit(2);
9
+ });