opena2a-cli 0.3.6 → 0.3.8

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 (46) hide show
  1. package/README.md +73 -12
  2. package/dist/adapters/registry.d.ts.map +1 -1
  3. package/dist/adapters/registry.js +13 -6
  4. package/dist/adapters/registry.js.map +1 -1
  5. package/dist/commands/identity.d.ts +12 -0
  6. package/dist/commands/identity.d.ts.map +1 -0
  7. package/dist/commands/identity.js +157 -0
  8. package/dist/commands/identity.js.map +1 -0
  9. package/dist/commands/init.d.ts.map +1 -1
  10. package/dist/commands/init.js +91 -39
  11. package/dist/commands/init.js.map +1 -1
  12. package/dist/commands/onepassword-migration.d.ts.map +1 -1
  13. package/dist/commands/onepassword-migration.js +7 -4
  14. package/dist/commands/onepassword-migration.js.map +1 -1
  15. package/dist/commands/protect.d.ts.map +1 -1
  16. package/dist/commands/protect.js +75 -19
  17. package/dist/commands/protect.js.map +1 -1
  18. package/dist/commands/runtime.d.ts.map +1 -1
  19. package/dist/commands/runtime.js +3 -3
  20. package/dist/commands/runtime.js.map +1 -1
  21. package/dist/commands/shield.d.ts.map +1 -1
  22. package/dist/commands/shield.js +3 -9
  23. package/dist/commands/shield.js.map +1 -1
  24. package/dist/commands/vault-migration.d.ts +17 -0
  25. package/dist/commands/vault-migration.d.ts.map +1 -0
  26. package/dist/commands/vault-migration.js +212 -0
  27. package/dist/commands/vault-migration.js.map +1 -0
  28. package/dist/index.js +27 -2
  29. package/dist/index.js.map +1 -1
  30. package/dist/router.d.ts.map +1 -1
  31. package/dist/router.js +32 -4
  32. package/dist/router.js.map +1 -1
  33. package/dist/util/colors.d.ts +1 -0
  34. package/dist/util/colors.d.ts.map +1 -1
  35. package/dist/util/colors.js +2 -1
  36. package/dist/util/colors.js.map +1 -1
  37. package/dist/util/credential-patterns.d.ts.map +1 -1
  38. package/dist/util/credential-patterns.js +11 -2
  39. package/dist/util/credential-patterns.js.map +1 -1
  40. package/dist/util/format.js +2 -2
  41. package/dist/util/format.js.map +1 -1
  42. package/dist/util/report-submission.d.ts +5 -0
  43. package/dist/util/report-submission.d.ts.map +1 -1
  44. package/dist/util/report-submission.js +64 -0
  45. package/dist/util/report-submission.js.map +1 -1
  46. package/package.json +1 -1
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  **Open-source security platform for AI agents**
6
6
 
7
- Credential detection, scope drift analysis, config integrity, runtime monitoring, and supply chain verification -- one CLI.
7
+ Credential detection, scope drift analysis, config integrity, runtime monitoring, behavioral governance scanning, and supply chain verification -- one CLI.
8
8
 
9
9
  [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/opena2a-org/opena2a/blob/main/LICENSE)
10
10
  [![Node](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)]()
@@ -36,7 +36,7 @@ No configuration required. Works with Node.js, Python, Go, and MCP server projec
36
36
  Run `opena2a init` in any project directory to get an instant security assessment:
37
37
 
38
38
  ```
39
- OpenA2A Security Report v0.3.6
39
+ OpenA2A Security Report v0.3.7
40
40
 
41
41
  Project myapp v2.1.0
42
42
  Type Node.js + MCP server
@@ -435,6 +435,8 @@ The CLI orchestrates these specialized tools through a unified interface:
435
435
  | Command | Tool | Description |
436
436
  |---------|------|-------------|
437
437
  | `opena2a scan` | [HackMyAgent](https://github.com/opena2a-org/hackmyagent) | 150+ security checks, attack simulation, auto-fix |
438
+ | `opena2a scan-soul` | [HackMyAgent](https://github.com/opena2a-org/hackmyagent) | Behavioral governance scan against AGS (SOUL.md) |
439
+ | `opena2a harden-soul` | [HackMyAgent](https://github.com/opena2a-org/hackmyagent) | Generate or improve SOUL.md governance file |
438
440
  | `opena2a secrets` | [Secretless AI](https://github.com/opena2a-org/secretless-ai) | Credential management for AI coding tools |
439
441
  | `opena2a benchmark` | [OASB](https://github.com/opena2a-org/oasb) | 222 attack scenarios, compliance scoring |
440
442
  | `opena2a registry` | [AI Trust](https://github.com/opena2a-org/ai-trust) | Trust Registry queries, package verification |
@@ -446,32 +448,91 @@ The CLI orchestrates these specialized tools through a unified interface:
446
448
 
447
449
  Adapters install tools on first use. Each tool works standalone or through the CLI.
448
450
 
451
+ ## Behavioral Governance
452
+
453
+ The [Agent Governance Specification (AGS)](https://github.com/opena2a-org/agent-governance-spec) defines a tiered behavioral safety framework for AI agents across 8 domains and 68 controls (OASB v2). OpenA2A CLI integrates AGS scanning through HackMyAgent.
454
+
455
+ ### `opena2a scan-soul`
456
+
457
+ Scan your governance file (SOUL.md or equivalent) against AGS controls for your agent's capability tier. Auto-detects tier from file content.
458
+
459
+ ```bash
460
+ opena2a scan-soul # Scan SOUL.md in current directory
461
+ opena2a scan-soul ./agent/ # Scan specific directory
462
+ opena2a scan-soul --tier TOOL-USING # Force TOOL-USING tier (54 controls)
463
+ opena2a scan-soul --tier AGENTIC # Force AGENTIC tier (65 controls)
464
+ opena2a scan-soul --tier MULTI-AGENT # Force MULTI-AGENT tier (68 controls)
465
+ opena2a scan-soul --json # Machine-readable output for CI
466
+ opena2a scan-soul --deep # Enable LLM semantic analysis (requires ANTHROPIC_API_KEY)
467
+ opena2a scan-soul --fail-below 60 # Exit 1 if score below threshold
468
+ ```
469
+
470
+ Tier-to-control mapping:
471
+
472
+ | Tier | Controls | Use Case |
473
+ |------|----------|----------|
474
+ | `BASIC` | 27 | Single-turn chatbots, no tool use |
475
+ | `TOOL-USING` | 54 | Agents with tool/function calling |
476
+ | `AGENTIC` | 65 | Long-running, multi-step autonomous agents |
477
+ | `MULTI-AGENT` | 68 | Orchestrators and sub-agent systems |
478
+
479
+ Governance file search order: `SOUL.md` > `system-prompt.md` > `CLAUDE.md` > `.cursorrules` > `agent-config.yaml` (and more).
480
+
481
+ Conformance levels shown in output:
482
+ - `none` — a critical control is missing (grade capped at C)
483
+ - `essential` — all critical controls pass
484
+ - `standard` — all critical + high controls pass, score ≥ 60
485
+ - `hardened` — all controls pass, score ≥ 75
486
+
487
+ ### `opena2a harden-soul`
488
+
489
+ Generate a SOUL.md governance file, or add missing sections to an existing one. Existing content is always preserved.
490
+
491
+ ```bash
492
+ opena2a harden-soul # Add missing sections to SOUL.md
493
+ opena2a harden-soul ./agent/ # Target specific directory
494
+ opena2a harden-soul --dry-run # Preview what would be added, no writes
495
+ opena2a harden-soul --json # Machine-readable output
496
+ ```
497
+
498
+ The 8 AGS behavioral domains (OASB v2, domains 7–14):
499
+
500
+ | Domain | What it governs |
501
+ |--------|----------------|
502
+ | Trust Hierarchy | Principal relationships, conflict resolution |
503
+ | Capability Boundaries | Allowed/denied actions, least privilege |
504
+ | Injection Hardening | Prompt injection defense, encoded payload rejection |
505
+ | Data Handling | PII protection, credential handling, data minimization |
506
+ | Hardcoded Behaviors | Immutable safety rules (no exfiltration, kill switch) |
507
+ | Agentic Safety | Iteration limits, budget caps, rollback, plan disclosure |
508
+ | Honesty and Transparency | Uncertainty acknowledgment, identity disclosure |
509
+ | Human Oversight | Approval gates, override mechanisms, monitoring |
510
+
449
511
  ## CI/CD Integration
450
512
 
451
- All commands support `--format json` and `--ci` flags for pipeline integration:
513
+ Several commands support `--json` output and `--fail-below` for pipeline gates:
452
514
 
453
515
  ```yaml
454
516
  # GitHub Actions example
455
- - name: Security assessment
456
- run: npx opena2a-cli init --ci --format json > security-report.json
457
-
458
517
  - name: Credential check
459
518
  run: |
460
- npx opena2a-cli protect --dry-run --ci --format json > cred-report.json
461
- # Fail if credentials found
519
+ npx opena2a-cli protect --dry-run --json > cred-report.json
462
520
  jq -e '.totalFound == 0' cred-report.json
463
521
 
522
+ - name: Behavioral governance gate
523
+ run: npx opena2a-cli scan-soul --json --fail-below 60
524
+
464
525
  - name: Config integrity
465
- run: npx opena2a-cli guard verify --ci
526
+ run: npx opena2a-cli guard verify
466
527
  ```
467
528
 
468
529
  ## Output Formats
469
530
 
470
531
  | Format | Flag | Use Case |
471
532
  |--------|------|----------|
472
- | Text | `--format text` (default) | Human-readable terminal output |
473
- | JSON | `--format json` | CI pipelines, programmatic consumption |
474
- | HTML | `--report <path>` | Interactive report with filtering (protect and shield report) |
533
+ | Text | (default) | Human-readable terminal output |
534
+ | JSON | `--json` | CI pipelines, programmatic consumption |
535
+ | HTML | `--report <path>` | Interactive report (protect and shield commands) |
475
536
 
476
537
  ## Credential Patterns
477
538
 
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAqD1D,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAElE;AAED,wBAAgB,YAAY,IAAI,aAAa,EAAE,CAE9C;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,EAAE,CAE1E"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CA4D1D,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAElE;AAED,wBAAgB,YAAY,IAAI,aAAa,EAAE,CAE9C;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,EAAE,CAE1E"}
@@ -24,6 +24,18 @@ exports.ADAPTER_REGISTRY = {
24
24
  packageName: 'hackmyagent',
25
25
  description: 'Run security benchmark against AI agent (OASB)',
26
26
  },
27
+ 'scan-soul': {
28
+ name: 'scan-soul',
29
+ method: 'import',
30
+ packageName: 'hackmyagent',
31
+ description: 'Scan governance file for behavioral safety coverage (AGS)',
32
+ },
33
+ 'harden-soul': {
34
+ name: 'harden-soul',
35
+ method: 'import',
36
+ packageName: 'hackmyagent',
37
+ description: 'Generate or improve governance file with AGS templates',
38
+ },
27
39
  registry: {
28
40
  name: 'registry',
29
41
  method: 'import',
@@ -42,12 +54,7 @@ exports.ADAPTER_REGISTRY = {
42
54
  pythonModule: 'cryptoserve',
43
55
  description: 'Cryptographic inventory and PQC readiness (CryptoServe)',
44
56
  },
45
- identity: {
46
- name: 'identity',
47
- method: 'spawn',
48
- command: 'aim',
49
- description: 'Agent identity management (AIM SDK)',
50
- },
57
+ // identity is now handled directly by packages/cli/src/commands/identity.ts
51
58
  // guard is now handled directly by packages/cli/src/commands/guard.ts (ConfigGuard)
52
59
  broker: {
53
60
  name: 'broker',
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":";;;AAyDA,gCAEC;AAED,oCAEC;AAED,kDAEC;AAjEY,QAAA,gBAAgB,GAAkC;IAC7D,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,0DAA0D;KACxE;IACD,OAAO,EAAE;QACP,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,qDAAqD;KACnE;IACD,0EAA0E;IAC1E,SAAS,EAAE;QACT,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,gDAAgD;KAC9D;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,wDAAwD;KACtE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,gDAAgD;KAC9D;IACD,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,QAAQ;QAChB,YAAY,EAAE,aAAa;QAC3B,WAAW,EAAE,yDAAyD;KACvE;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,KAAK;QACd,WAAW,EAAE,qCAAqC;KACnD;IACD,oFAAoF;IACpF,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,eAAe;QAC5B,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,yCAAyC;KACvD;IACD,iFAAiF;CAClF,CAAC;AAEF,SAAgB,UAAU,CAAC,IAAY;IACrC,OAAO,wBAAgB,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,SAAgB,YAAY;IAC1B,OAAO,MAAM,CAAC,MAAM,CAAC,wBAAgB,CAAC,CAAC;AACzC,CAAC;AAED,SAAgB,mBAAmB,CAAC,MAAqB;IACvD,OAAO,MAAM,CAAC,MAAM,CAAC,wBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;AAC1E,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/adapters/registry.ts"],"names":[],"mappings":";;;AAgEA,gCAEC;AAED,oCAEC;AAED,kDAEC;AAxEY,QAAA,gBAAgB,GAAkC;IAC7D,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,0DAA0D;KACxE;IACD,OAAO,EAAE;QACP,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,eAAe;QAC5B,WAAW,EAAE,qDAAqD;KACnE;IACD,0EAA0E;IAC1E,SAAS,EAAE;QACT,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,gDAAgD;KAC9D;IACD,WAAW,EAAE;QACX,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,2DAA2D;KACzE;IACD,aAAa,EAAE;QACb,IAAI,EAAE,aAAa;QACnB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,aAAa;QAC1B,WAAW,EAAE,wDAAwD;KACtE;IACD,QAAQ,EAAE;QACR,IAAI,EAAE,UAAU;QAChB,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,UAAU;QACvB,WAAW,EAAE,wDAAwD;KACtE;IACD,KAAK,EAAE;QACL,IAAI,EAAE,OAAO;QACb,MAAM,EAAE,QAAQ;QAChB,KAAK,EAAE,cAAc;QACrB,WAAW,EAAE,gDAAgD;KAC9D;IACD,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,QAAQ;QAChB,YAAY,EAAE,aAAa;QAC3B,WAAW,EAAE,yDAAyD;KACvE;IACD,4EAA4E;IAC5E,oFAAoF;IACpF,MAAM,EAAE;QACN,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,eAAe;QAC5B,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,yCAAyC;KACvD;IACD,iFAAiF;CAClF,CAAC;AAEF,SAAgB,UAAU,CAAC,IAAY;IACrC,OAAO,wBAAgB,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,SAAgB,YAAY;IAC1B,OAAO,MAAM,CAAC,MAAM,CAAC,wBAAgB,CAAC,CAAC;AACzC,CAAC;AAED,SAAgB,mBAAmB,CAAC,MAAqB;IACvD,OAAO,MAAM,CAAC,MAAM,CAAC,wBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,12 @@
1
+ interface IdentityOptions {
2
+ subcommand: string;
3
+ name?: string;
4
+ limit?: number;
5
+ dir?: string;
6
+ ci?: boolean;
7
+ format?: string;
8
+ verbose?: boolean;
9
+ }
10
+ export declare function identity(options: IdentityOptions): Promise<number>;
11
+ export {};
12
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../src/commands/identity.ts"],"names":[],"mappings":"AAGA,UAAU,eAAe;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBxE"}
@@ -0,0 +1,157 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.identity = identity;
4
+ const colors_js_1 = require("../util/colors.js");
5
+ async function identity(options) {
6
+ const sub = options.subcommand;
7
+ switch (sub) {
8
+ case 'list':
9
+ case 'show':
10
+ return handleList(options);
11
+ case 'create':
12
+ return handleCreate(options);
13
+ case 'trust':
14
+ return handleTrust(options);
15
+ case 'audit':
16
+ return handleAudit(options);
17
+ default:
18
+ process.stderr.write(`Unknown identity subcommand: ${sub}\n`);
19
+ process.stderr.write('\nUsage: opena2a identity <list|create|trust|audit>\n\n');
20
+ process.stderr.write(' list Show local agent identity\n');
21
+ process.stderr.write(' create --name <n> Create a new agent identity\n');
22
+ process.stderr.write(' trust Show trust score\n');
23
+ process.stderr.write(' audit [--limit N] Show recent audit events\n');
24
+ return 1;
25
+ }
26
+ }
27
+ async function loadAimCore() {
28
+ try {
29
+ return await import('@opena2a/aim-core');
30
+ }
31
+ catch {
32
+ process.stderr.write('aim-core is not available.\n');
33
+ process.stderr.write('Install: npm install @opena2a/aim-core\n');
34
+ return null;
35
+ }
36
+ }
37
+ async function handleList(options) {
38
+ const mod = await loadAimCore();
39
+ if (!mod)
40
+ return 1;
41
+ const isJson = options.format === 'json';
42
+ try {
43
+ const aim = new mod.AIMCore({ agentName: 'default' });
44
+ const id = aim.getIdentity();
45
+ if (isJson) {
46
+ process.stdout.write(JSON.stringify(id, null, 2) + '\n');
47
+ return 0;
48
+ }
49
+ process.stdout.write((0, colors_js_1.bold)('Agent Identity') + '\n');
50
+ process.stdout.write((0, colors_js_1.gray)('-'.repeat(50)) + '\n');
51
+ process.stdout.write(` Agent ID: ${(0, colors_js_1.cyan)(id.agentId)}\n`);
52
+ process.stdout.write(` Name: ${id.agentName}\n`);
53
+ process.stdout.write(` Public Key: ${(0, colors_js_1.dim)(id.publicKey.slice(0, 32) + '...')}\n`);
54
+ process.stdout.write(` Created: ${id.createdAt}\n`);
55
+ process.stdout.write((0, colors_js_1.gray)('-'.repeat(50)) + '\n');
56
+ return 0;
57
+ }
58
+ catch (err) {
59
+ process.stderr.write(`Failed to load identity: ${err instanceof Error ? err.message : String(err)}\n`);
60
+ return 1;
61
+ }
62
+ }
63
+ async function handleCreate(options) {
64
+ const mod = await loadAimCore();
65
+ if (!mod)
66
+ return 1;
67
+ const name = options.name;
68
+ if (!name) {
69
+ process.stderr.write('Missing required option: --name <name>\n');
70
+ process.stderr.write('Usage: opena2a identity create --name my-agent\n');
71
+ return 1;
72
+ }
73
+ const isJson = options.format === 'json';
74
+ try {
75
+ const aim = new mod.AIMCore({ agentName: name });
76
+ const id = aim.getIdentity();
77
+ if (isJson) {
78
+ process.stdout.write(JSON.stringify(id, null, 2) + '\n');
79
+ return 0;
80
+ }
81
+ process.stdout.write((0, colors_js_1.green)('Identity created') + '\n');
82
+ process.stdout.write(` Agent ID: ${(0, colors_js_1.cyan)(id.agentId)}\n`);
83
+ process.stdout.write(` Name: ${id.agentName}\n`);
84
+ process.stdout.write(` Public Key: ${(0, colors_js_1.dim)(id.publicKey.slice(0, 32) + '...')}\n`);
85
+ process.stdout.write(` Stored in: ${(0, colors_js_1.dim)(aim.getDataDir())}\n`);
86
+ return 0;
87
+ }
88
+ catch (err) {
89
+ process.stderr.write(`Failed to create identity: ${err instanceof Error ? err.message : String(err)}\n`);
90
+ return 1;
91
+ }
92
+ }
93
+ async function handleTrust(options) {
94
+ const mod = await loadAimCore();
95
+ if (!mod)
96
+ return 1;
97
+ const isJson = options.format === 'json';
98
+ try {
99
+ const aim = new mod.AIMCore({ agentName: 'default' });
100
+ aim.getIdentity(); // ensure identity exists
101
+ const trust = aim.calculateTrust();
102
+ if (isJson) {
103
+ process.stdout.write(JSON.stringify(trust, null, 2) + '\n');
104
+ return 0;
105
+ }
106
+ process.stdout.write((0, colors_js_1.bold)('Trust Score') + '\n');
107
+ process.stdout.write((0, colors_js_1.gray)('-'.repeat(50)) + '\n');
108
+ process.stdout.write(` Score: ${(0, colors_js_1.bold)(String(trust.score))} Grade: ${(0, colors_js_1.bold)(trust.grade)}\n`);
109
+ process.stdout.write('\n');
110
+ process.stdout.write(' Factors:\n');
111
+ for (const [factor, value] of Object.entries(trust.factors)) {
112
+ const label = factor.replace(/([A-Z])/g, ' $1').toLowerCase().trim();
113
+ const status = value > 0 ? (0, colors_js_1.green)('active') : (0, colors_js_1.dim)('inactive');
114
+ process.stdout.write(` ${label.padEnd(22)} ${status}\n`);
115
+ }
116
+ process.stdout.write((0, colors_js_1.gray)('-'.repeat(50)) + '\n');
117
+ return 0;
118
+ }
119
+ catch (err) {
120
+ process.stderr.write(`Failed to calculate trust: ${err instanceof Error ? err.message : String(err)}\n`);
121
+ return 1;
122
+ }
123
+ }
124
+ async function handleAudit(options) {
125
+ const mod = await loadAimCore();
126
+ if (!mod)
127
+ return 1;
128
+ const isJson = options.format === 'json';
129
+ const limit = options.limit ?? 10;
130
+ try {
131
+ const aim = new mod.AIMCore({ agentName: 'default' });
132
+ const events = aim.readAuditLog({ limit });
133
+ if (isJson) {
134
+ process.stdout.write(JSON.stringify(events, null, 2) + '\n');
135
+ return 0;
136
+ }
137
+ if (events.length === 0) {
138
+ process.stdout.write((0, colors_js_1.dim)('No audit events recorded yet.') + '\n');
139
+ process.stdout.write((0, colors_js_1.dim)('Events are logged when using aim-core in your agent.') + '\n');
140
+ return 0;
141
+ }
142
+ process.stdout.write((0, colors_js_1.bold)(`Audit Log (last ${events.length})`) + '\n');
143
+ process.stdout.write((0, colors_js_1.gray)('-'.repeat(70)) + '\n');
144
+ for (const e of events) {
145
+ const ts = e.timestamp.slice(0, 19).replace('T', ' ');
146
+ const resultColor = e.result === 'allowed' ? colors_js_1.green : e.result === 'denied' ? colors_js_1.yellow : colors_js_1.dim;
147
+ process.stdout.write(` ${(0, colors_js_1.dim)(ts)} ${e.action.padEnd(16)} ${e.target.padEnd(16)} ${resultColor(e.result)}\n`);
148
+ }
149
+ process.stdout.write((0, colors_js_1.gray)('-'.repeat(70)) + '\n');
150
+ return 0;
151
+ }
152
+ catch (err) {
153
+ process.stderr.write(`Failed to read audit log: ${err instanceof Error ? err.message : String(err)}\n`);
154
+ return 1;
155
+ }
156
+ }
157
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../src/commands/identity.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH,OAAO,EACL,sBAAsB,IAAI,4BAA4B,EAKvD,MAAM,oBAAoB,CAAC;AAI5B,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA0DD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAiMhE;AAmQD;;;GAGG;AACH,eAAO,MAAM,sBAAsB,qCAA+B,CAAC"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH,OAAO,EACL,sBAAsB,IAAI,4BAA4B,EAKvD,MAAM,oBAAoB,CAAC;AAI5B,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AA0DD,wBAAsB,IAAI,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAwOhE;AAmQD;;;GAGG;AACH,eAAO,MAAM,sBAAsB,qCAA+B,CAAC"}
@@ -219,22 +219,58 @@ async function init(options) {
219
219
  if (driftFindings.length > 0) {
220
220
  process.stdout.write((0, colors_js_1.yellow)((0, colors_js_1.bold)(' Scope Drift Detected')) + '\n');
221
221
  process.stdout.write((0, colors_js_1.gray)(' ' + '-'.repeat(47)) + '\n');
222
+ // Group by drift type and show once per type with count
223
+ const driftByType = new Map();
222
224
  for (const d of driftFindings) {
223
- const relPath = path.relative(targetDir, d.filePath);
224
- const driftType = d.findingId === 'DRIFT-001' ? 'Google Maps key may access Gemini AI' : 'AWS key may access Bedrock AI';
225
- process.stdout.write(` ${(0, colors_js_1.yellow)(d.findingId)} ${driftType}\n`);
226
- process.stdout.write(` ${(0, colors_js_1.dim)(' ' + relPath + ':' + d.line)}\n`);
225
+ const existing = driftByType.get(d.findingId) ?? [];
226
+ existing.push(d);
227
+ driftByType.set(d.findingId, existing);
228
+ }
229
+ for (const [findingId, items] of driftByType) {
230
+ const first = items[0];
231
+ const relPath = path.relative(targetDir, first.filePath);
232
+ const extra = items.length > 1 ? ` (+${items.length - 1} more)` : '';
233
+ if (findingId === 'DRIFT-001') {
234
+ process.stdout.write(` ${(0, colors_js_1.yellow)(findingId)} Google Maps key may access Gemini AI (${items.length} location${items.length === 1 ? '' : 's'})\n`);
235
+ process.stdout.write(` ${(0, colors_js_1.dim)(' ' + relPath + ':' + first.line + extra)}\n`);
236
+ process.stdout.write(` ${(0, colors_js_1.dim)(' Keys provisioned for Maps silently authenticate to Gemini if the')}\n`);
237
+ process.stdout.write(` ${(0, colors_js_1.dim)(' Generative Language API is enabled in the same GCP project.')}\n`);
238
+ process.stdout.write(` ${(0, colors_js_1.dim)(' Verify: opena2a protect --dry-run')}\n`);
239
+ process.stdout.write(` ${(0, colors_js_1.dim)(' (runs live Gemini API access check, no changes made)')}\n`);
240
+ process.stdout.write(` ${(0, colors_js_1.dim)(' Fix: opena2a protect')}\n`);
241
+ }
242
+ else if (findingId === 'DRIFT-002') {
243
+ process.stdout.write(` ${(0, colors_js_1.yellow)(findingId)} AWS key may access Bedrock AI (${items.length} location${items.length === 1 ? '' : 's'})\n`);
244
+ process.stdout.write(` ${(0, colors_js_1.dim)(' ' + relPath + ':' + first.line + extra)}\n`);
245
+ process.stdout.write(` ${(0, colors_js_1.dim)(' IAM policies frequently over-provision. A key scoped for S3/EC2')}\n`);
246
+ process.stdout.write(` ${(0, colors_js_1.dim)(' may also pass STS auth and call Bedrock LLM endpoints.')}\n`);
247
+ process.stdout.write(` ${(0, colors_js_1.dim)(' Verify: opena2a protect --dry-run')}\n`);
248
+ process.stdout.write(` ${(0, colors_js_1.dim)(' (runs live STS + Bedrock access check, no changes made)')}\n`);
249
+ process.stdout.write(` ${(0, colors_js_1.dim)(' Fix: opena2a protect')}\n`);
250
+ }
251
+ else {
252
+ process.stdout.write(` ${(0, colors_js_1.yellow)(findingId)} Credential scope drift (${items.length} location${items.length === 1 ? '' : 's'})\n`);
253
+ process.stdout.write(` ${(0, colors_js_1.dim)(' ' + relPath + ':' + first.line + extra)}\n`);
254
+ process.stdout.write(` ${(0, colors_js_1.dim)(' Verify: opena2a protect --dry-run')}\n`);
255
+ process.stdout.write(` ${(0, colors_js_1.dim)(' Fix: opena2a protect')}\n`);
256
+ }
257
+ process.stdout.write('\n');
227
258
  }
228
- process.stdout.write('\n');
229
- process.stdout.write((0, colors_js_1.dim)(' Scope drift: keys provisioned for one service silently') + '\n');
230
- process.stdout.write((0, colors_js_1.dim)(' gain access to AI services, expanding attack surface.') + '\n');
231
- process.stdout.write((0, colors_js_1.dim)(' Run: opena2a protect') + '\n');
232
- process.stdout.write('\n');
233
259
  }
234
260
  // Show advisory warnings after main report
235
261
  if (advisoryCheck.advisories.length > 0) {
236
262
  (0, advisories_js_1.printAdvisoryWarnings)(advisoryCheck);
237
263
  }
264
+ // Contextual tip
265
+ const tip = getContextualTip(report);
266
+ process.stdout.write((0, colors_js_1.dim)(` Tip: ${tip.command}`) + '\n');
267
+ const wrappedTipText = (0, format_js_1.wordWrap)(tip.text, 68, 7);
268
+ process.stdout.write((0, colors_js_1.dim)(wrappedTipText) + '\n');
269
+ process.stdout.write('\n');
270
+ // OpenA2A footer
271
+ process.stdout.write((0, colors_js_1.cyan)(' OpenA2A -- open-source security for AI agents') + '\n');
272
+ process.stdout.write((0, colors_js_1.cyan)(' opena2a.org | github.com/opena2a-org') + '\n');
273
+ process.stdout.write('\n');
238
274
  }
239
275
  const hasCritical = nextSteps.some(s => s.severity === 'critical');
240
276
  return hasCritical ? 1 : 0;
@@ -697,55 +733,71 @@ function getToolRecommendation(findingId) {
697
733
  return null;
698
734
  }
699
735
  function getContextualTip(report) {
700
- const hasAnyCreds = report.findings.some(f => f.findingId.startsWith('CRED-') || f.findingId.startsWith('DRIFT-'));
701
- if (hasAnyCreds) {
736
+ const credCount = report.credentialFindings;
737
+ const criticalCount = report.credentialsBySeverity['critical'] ?? 0;
738
+ const driftFindings = report.findings.filter(f => f.findingId.startsWith('DRIFT-'));
739
+ const hasDrift = driftFindings.length > 0;
740
+ const hasAwsDrift = report.findings.some(f => f.findingId === 'DRIFT-002');
741
+ const hasGcpDrift = report.findings.some(f => f.findingId === 'DRIFT-001');
742
+ if (credCount > 0) {
743
+ if (hasDrift && hasAwsDrift) {
744
+ return {
745
+ text: `${credCount} credential${credCount === 1 ? '' : 's'} in source files, including AWS keys with potential Bedrock access. opena2a protect moves them to Secretless AI (encrypted local vault) and runs a live STS + Bedrock check to confirm actual exposure.`,
746
+ command: 'opena2a protect',
747
+ };
748
+ }
749
+ if (hasDrift && hasGcpDrift) {
750
+ return {
751
+ text: `${credCount} credential${credCount === 1 ? '' : 's'} in source files, including Google keys with potential Gemini access. opena2a protect moves them to Secretless AI (encrypted local vault) and verifies live Generative Language API access.`,
752
+ command: 'opena2a protect',
753
+ };
754
+ }
755
+ if (criticalCount > 0) {
756
+ return {
757
+ text: `${criticalCount} critical credential${criticalCount === 1 ? '' : 's'} in source files — anyone with repo access can use them now. opena2a protect moves them to Secretless AI (encrypted local vault) and rewrites the source files to reference env vars.`,
758
+ command: 'opena2a protect',
759
+ };
760
+ }
702
761
  return {
703
- text: 'Migrate credentials out of source files',
762
+ text: `${credCount} credential${credCount === 1 ? '' : 's'} in source files. opena2a protect moves them to Secretless AI, rewrites the source to use env var references, and updates .gitignore.`,
704
763
  command: 'opena2a protect',
705
764
  };
706
765
  }
707
766
  const hasMcpCred = report.findings.some(f => f.findingId === 'MCP-CRED');
708
767
  if (hasMcpCred) {
709
768
  return {
710
- text: 'Move credentials out of MCP config files',
769
+ text: 'Credentials in MCP config files are read by every AI tool that loads the config. opena2a protect moves them to Secretless AI and injects them as env vars at runtime — no more plaintext in config files.',
711
770
  command: 'opena2a protect',
712
771
  };
713
772
  }
714
773
  const hasAiConfig = report.findings.some(f => f.findingId === 'AI-CONFIG');
715
774
  if (hasAiConfig) {
716
775
  return {
717
- text: 'Fix all auto-fixable findings',
776
+ text: 'AI tool config files (Claude, Cursor, Copilot) have fixable issues. opena2a protect applies all auto-fixable changes in one pass and signs the files so Guard can detect future unauthorized changes.',
718
777
  command: 'opena2a protect',
719
778
  };
720
779
  }
721
780
  const hasLLM = report.findings.some(f => f.findingId === 'ENV-LLM');
722
781
  if (hasLLM) {
723
782
  return {
724
- text: 'Add authentication to your LLM server',
783
+ text: 'An unauthenticated LLM server is running locally. opena2a shield status shows which Shield modules are active and what ARP is monitoring at the process and network level.',
725
784
  command: 'opena2a shield status',
726
785
  };
727
786
  }
728
- const hasEnv = report.findings.some(f => f.findingId === 'ENV-DOTENV');
729
- if (hasEnv) {
730
- return {
731
- text: 'Fix all auto-fixable findings',
732
- command: 'opena2a protect',
733
- };
734
- }
735
787
  if (report.securityScore >= 90) {
736
788
  return {
737
- text: 'Strong baseline. Run a full scan for deeper coverage',
738
- command: 'opena2a scan secure',
789
+ text: 'Strong baseline. HackMyAgent runs 147 checks including agent-layer attacks, MCP exploitation, and OASB-1 + OASB-2 compliance scoring.',
790
+ command: 'npx hackmyagent secure',
739
791
  };
740
792
  }
741
793
  if (report.securityScore >= 70) {
742
794
  return {
743
- text: 'Good posture. Lock it in with config file integrity signing',
795
+ text: 'Good posture. opena2a guard sign creates signed baselines for your config files Guard will alert if anything changes without a new signature.',
744
796
  command: 'opena2a guard sign',
745
797
  };
746
798
  }
747
799
  return {
748
- text: 'See all available security tools',
800
+ text: 'opena2a shield status shows all active protections: ARP runtime monitoring, Guard config integrity, Secretless credential management, and HackMyAgent scan coverage.',
749
801
  command: 'opena2a shield status',
750
802
  };
751
803
  }
@@ -783,13 +835,18 @@ function printReport(report, elapsed, verbose) {
783
835
  if (report.findings.length > 0) {
784
836
  process.stdout.write((0, colors_js_1.bold)(' Findings') + '\n');
785
837
  process.stdout.write((0, colors_js_1.gray)(' ' + '-'.repeat(47)) + '\n');
786
- const maxFindings = verbose ? report.findings.length : 5;
787
- const displayFindings = report.findings.slice(0, maxFindings);
838
+ // Always show all critical + high; truncate medium/low at 2 (unless verbose)
839
+ const important = report.findings.filter(f => f.severity === 'critical' || f.severity === 'high');
840
+ const minor = report.findings.filter(f => f.severity !== 'critical' && f.severity !== 'high');
841
+ const maxMinor = verbose ? minor.length : 2;
842
+ const displayFindings = [...important, ...minor.slice(0, maxMinor)];
843
+ const hiddenCount = verbose ? 0 : minor.length - maxMinor;
788
844
  for (const finding of displayFindings) {
789
- const sevTag = finding.severity === 'critical' ? (0, colors_js_1.red)('CRITICAL')
790
- : finding.severity === 'high' ? (0, colors_js_1.yellow)('HIGH ')
791
- : finding.severity === 'medium' ? (0, colors_js_1.cyan)('MEDIUM ')
792
- : (0, colors_js_1.dim)('LOW ');
845
+ const sevPad = finding.severity === 'critical' ? ''
846
+ : finding.severity === 'high' ? ' '
847
+ : finding.severity === 'medium' ? ' '
848
+ : ' ';
849
+ const sevTag = (0, format_js_1.severityColor)(finding.severity)(finding.severity.toUpperCase()) + sevPad;
793
850
  const countPrefix = finding.count > 1 ? `${finding.count} ` : '';
794
851
  process.stdout.write(` ${sevTag} ${countPrefix}${(0, colors_js_1.bold)(finding.title)}\n`);
795
852
  if (finding.explanation) {
@@ -821,9 +878,8 @@ function printReport(report, elapsed, verbose) {
821
878
  }
822
879
  process.stdout.write('\n');
823
880
  }
824
- if (!verbose && report.findings.length > maxFindings) {
825
- const remaining = report.findings.length - maxFindings;
826
- process.stdout.write((0, colors_js_1.dim)(` [+${remaining} more finding${remaining === 1 ? '' : 's'} -- run with --verbose to see all]`) + '\n');
881
+ if (hiddenCount > 0) {
882
+ process.stdout.write((0, colors_js_1.dim)(` [+${hiddenCount} lower-severity finding${hiddenCount === 1 ? '' : 's'} -- run with --verbose to see all]`) + '\n');
827
883
  process.stdout.write('\n');
828
884
  }
829
885
  }
@@ -877,9 +933,5 @@ function printReport(report, elapsed, verbose) {
877
933
  process.stdout.write((0, colors_js_1.gray)(' ' + '-'.repeat(47)) + '\n');
878
934
  }
879
935
  process.stdout.write('\n');
880
- // Contextual tip
881
- const tip = getContextualTip(report);
882
- process.stdout.write((0, colors_js_1.dim)(` Tip: ${tip.command} -- ${tip.text}`) + '\n');
883
- process.stdout.write('\n');
884
936
  }
885
937
  //# sourceMappingURL=init.js.map