multimodel-dev-os 3.2.0 → 3.5.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.
Files changed (68) hide show
  1. package/.ai/policies/registry-policy.yaml +29 -1
  2. package/.ai/registries/trusted-keys.yaml +12 -0
  3. package/.ai/schema/registry-manifest.schema.json +31 -2
  4. package/.ai/schema/registry-policy.schema.json +37 -1
  5. package/.ai/schema/trusted-keys.schema.json +69 -0
  6. package/AGENTS.md +22 -26
  7. package/MEMORY.md +34 -11
  8. package/README.md +1 -1
  9. package/RUNBOOK.md +28 -36
  10. package/TASKS.md +15 -5
  11. package/bin/multimodel-dev-os.js +1366 -548
  12. package/docs/.vitepress/config.js +3 -1
  13. package/docs/architecture.md +3 -1
  14. package/docs/index.md +5 -5
  15. package/docs/npm-publishing.md +5 -5
  16. package/docs/package-safety.md +3 -2
  17. package/docs/public/llms-full.txt +5 -1
  18. package/docs/public/llms.txt +6 -1
  19. package/docs/public/sitemap.xml +10 -0
  20. package/docs/registry-policy.md +29 -1
  21. package/docs/registry-security.md +73 -6
  22. package/docs/registry-signing.md +70 -0
  23. package/docs/registry-sync.md +5 -2
  24. package/docs/registry-trust-store.md +66 -0
  25. package/docs/release-policy.md +1 -1
  26. package/docs/security-threat-model.md +96 -0
  27. package/docs/testing.md +15 -2
  28. package/docs/trusted-registries.md +1 -1
  29. package/docs/v3-roadmap.md +11 -6
  30. package/docs/v3.5.0-readiness.md +46 -0
  31. package/package.json +1 -1
  32. package/scripts/install.ps1 +1 -1
  33. package/scripts/install.sh +1 -1
  34. package/scripts/verify.js +206 -9
  35. package/src/cli/help.js +1 -1
  36. package/src/cli/main.js +626 -81
  37. package/src/core/policy.js +9 -1
  38. package/src/registry/provenance.js +114 -0
  39. package/src/registry/signing.js +392 -0
  40. package/src/registry/trust-store.js +41 -0
  41. package/src/registry/verdict.js +51 -0
  42. package/tests/fixtures/signed-registries/README.md +4 -0
  43. package/tests/fixtures/signed-registries/revoked-key/catalog.yaml +8 -0
  44. package/tests/fixtures/signed-registries/revoked-key/expected-verdict.json +7 -0
  45. package/tests/fixtures/signed-registries/revoked-key/registry-manifest.yaml +14 -0
  46. package/tests/fixtures/signed-registries/tampered-manifest/catalog.yaml +8 -0
  47. package/tests/fixtures/signed-registries/tampered-manifest/expected-verdict.json +7 -0
  48. package/tests/fixtures/signed-registries/tampered-manifest/registry-manifest.yaml +14 -0
  49. package/tests/fixtures/signed-registries/trusted-keys.yaml +23 -0
  50. package/tests/fixtures/signed-registries/unsigned-remote-required/catalog.yaml +8 -0
  51. package/tests/fixtures/signed-registries/unsigned-remote-required/expected-verdict.json +7 -0
  52. package/tests/fixtures/signed-registries/unsigned-remote-required/registry-manifest.yaml +9 -0
  53. package/tests/fixtures/signed-registries/unsupported-algorithm/catalog.yaml +8 -0
  54. package/tests/fixtures/signed-registries/unsupported-algorithm/expected-verdict.json +7 -0
  55. package/tests/fixtures/signed-registries/unsupported-algorithm/registry-manifest.yaml +14 -0
  56. package/tests/fixtures/signed-registries/valid-signed-registry/catalog.yaml +8 -0
  57. package/tests/fixtures/signed-registries/valid-signed-registry/expected-verdict.json +7 -0
  58. package/tests/fixtures/signed-registries/valid-signed-registry/registry-manifest.yaml +14 -0
  59. package/tests/fixtures/signed-registries/wrong-key/catalog.yaml +8 -0
  60. package/tests/fixtures/signed-registries/wrong-key/expected-verdict.json +7 -0
  61. package/tests/fixtures/signed-registries/wrong-key/registry-manifest.yaml +14 -0
  62. package/tests/unit/registry-e2e-signature-fixtures.test.js +288 -0
  63. package/tests/unit/registry-policy.test.js +6 -0
  64. package/tests/unit/registry-provenance.test.js +185 -0
  65. package/tests/unit/registry-public-signing.test.js +109 -0
  66. package/tests/unit/registry-signature-policy.test.js +100 -0
  67. package/tests/unit/registry-signing.test.js +193 -0
  68. package/tests/unit/registry-trust-store.test.js +133 -0
@@ -7,12 +7,19 @@ This document outlines the development path, completed milestones, and future pl
7
7
  ## 1. Current Status
8
8
 
9
9
  > [!IMPORTANT]
10
- > **v3.2.0 is the active stable release** on the public npm registry. All features below marked ✅ are shipped and production-ready.
10
+ > **v3.5.0 is the active stable release** on the public npm registry. All features below marked ✅ are shipped and production-ready.
11
11
 
12
12
  ---
13
13
 
14
14
  ## 2. Completed Milestones
15
15
 
16
+ ### v3.5.0 — Trusted Registry Signing + Provenance ✅
17
+ - **Asymmetric Ed25519 Signatures**: Cryptographic verification of remote registry manifests using publisher public keys to secure remote sync.
18
+ - **Trusted Key Store**: Manages active public keys, publishers, and scopes via `.ai/registries/trusted-keys.yaml` configuration.
19
+ - **Registry Provenance Lockfile**: Keeps a committed `.ai/registry-lock.json` containing synced hashes, timestamps, and verdicts to detect local cache tampering.
20
+ - **Structured Verdicts**: Deployed `createTrustVerdict` to generate uniform verification reporting for CLI audits, lockfiles, and diagnostics.
21
+ - **Signed Registry E2E Fixtures**: Comprehensive offline test suite validating valid, tampered, wrong key, revoked key, unsigned, and unsupported algorithm states.
22
+
16
23
  ### v3.2.0 — Stable Modular Build + Package Governance ✅
17
24
  - **Build Freshness Auditing**: Integrated `check-build-fresh.js` to ensure the generated single-file CLI binary matches standard ES modules under `src/` dynamically.
18
25
  - **Hardened Package Governance**: Configured the NPM manifest (`package.json`) to include the modular source folder (`src/`) and unit test suites (`tests/unit/`) for developer auditability, while verifying the strict exclusion of sensitive and temporary files.
@@ -80,11 +87,9 @@ All releases follow this strict publishing checklist:
80
87
 
81
88
  ---
82
89
 
83
- ## 4. Upcoming: v3.3.0 stable candidateAsymmetric Key Signatures
84
-
85
- * **Asymmetric Key Signatures**: Cryptographic signature validation for remote registries using public/private key pairs.
86
- * **Decentralized Trust Anchors**: Trust anchors configuration allowing teams to pin public keys of verified catalog authors.
87
- * **Tamper-Proof Audit Chain**: Signed change logs and history verification.
90
+ ## 4. In Progress: v3.6.0-prep / Sprint 4 Remote Key Sync & GPG Signatures
91
+ - **Remote Key Sync**: Enable syncing public keys directly from approved remote registries.
92
+ - **GPG Compatibility**: Support GPG signatures for enterprise-controlled repositories.
88
93
 
89
94
  ---
90
95
 
@@ -0,0 +1,46 @@
1
+ # v3.5.0 Release Readiness Checklist
2
+
3
+ This document tracks the release readiness checklist for MultiModel Dev OS v3.5.0.
4
+ The v3.5.0 milestone represents the integration of HMAC-SHA256 provenance lockfiles, Ed25519 public-key signature checks, and the trusted publisher key store.
5
+
6
+ ---
7
+
8
+ ## Release Governance Status
9
+
10
+ > [!WARNING]
11
+ > **Status:** `Pending (Internal Preparation)`
12
+ > This is an unreleased internal development build. Do not tag, publish to npm, or mark v3.5.0 as released.
13
+
14
+ ---
15
+
16
+ ## Readiness Checklist
17
+
18
+ ### 1. Cryptography and Identity Trust
19
+ - [x] **Ed25519 Public-Key Signatures**: Asymmetric signing and timing-safe verification verified end-to-end using Node.js built-ins.
20
+ - [x] **Zero Runtime Dependencies**: Cryptographic functions use native Node `crypto` only.
21
+ - [x] **Trust Store**: Key loading and parsing validated with active status, expiration, and scope constraint checks.
22
+ - [x] **Deterministic Serialization**: Canonical payload sorting proven stable and deterministic across platforms.
23
+
24
+ ### 2. End-to-End Fixtures
25
+ - [x] **Valid Signed Registry**: Proven to pass verification.
26
+ - [x] **Tampered Manifest**: Rejected during verification with signature verification errors.
27
+ - [x] **Wrong Signing Key**: Rejected as untrusted.
28
+ - [x] **Revoked/Disabled Keys**: Correctly blocked by trust store status gates.
29
+ - [x] **Unsupported Algorithms**: Properly rejected by policy validation.
30
+ - [x] **Lockfile & Provenance Integrity**: Local `registry-lock.json` entries record precise verdicts and error details.
31
+
32
+ ### 3. Build & Package Hygiene
33
+ - [x] **Generated CLI Freshness**: `scripts/check-build-fresh.js` validates that `bin/multimodel-dev-os.js` matches the `src/` modules.
34
+ - [x] **Shebang & Header Validations**: Generated binary has exactly one shebang and includes the warning header.
35
+ - [x] **No Private Keys Committed**: No private keys or `.ai/registry-signing-key` files are tracked by Git.
36
+ - [x] **Clean Packing Exclusion**: Manifest configuration filters out `.npmrc`, `.env`, private keys, local tarballs, and temporary smoke directories.
37
+
38
+ ### 4. Command Safety & UX
39
+ - [x] **URL Safety Gate**: No shell-based URL interpolation is used. Synchronous fetching uses `execFileSync` arguments.
40
+ - [x] **Approval Gated Sync**: `registry sync` strictly requires `--approved` flag before performing network fetches.
41
+ - [x] **Offline Stability**: Registry verification and catalog features operate offline using cache directory fixtures.
42
+
43
+ ### 5. Verification Metrics
44
+ - [x] **Unit Test Suite**: All unit tests pass cleanly.
45
+ - [x] **Strict Verification Assertions**: `scripts/verify.js` executes successfully with zero failures.
46
+ - [x] **Documentation Coverage**: Threat models, architecture guides, policies, and roadmap files are updated.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "multimodel-dev-os",
3
- "version": "3.2.0",
3
+ "version": "3.5.0",
4
4
  "bin": {
5
5
  "multimodel-dev-os": "bin/multimodel-dev-os.js"
6
6
  },
@@ -11,7 +11,7 @@ param(
11
11
  [switch]$Help
12
12
  )
13
13
 
14
- $Version = "3.2.0"
14
+ $Version = "3.5.0"
15
15
  $RepoUrl = "https://raw.githubusercontent.com/rizvee/multimodel-dev-os/main"
16
16
 
17
17
  if ($Help) {
@@ -7,7 +7,7 @@ set -euo pipefail
7
7
  # --all (install all adapters)
8
8
  # --dry-run (show what would be created without creating)
9
9
 
10
- VERSION="3.2.0"
10
+ VERSION="3.5.0"
11
11
  REPO_URL="https://raw.githubusercontent.com/rizvee/multimodel-dev-os/main"
12
12
  CAVEMAN=false
13
13
  DRY_RUN=false
package/scripts/verify.js CHANGED
@@ -201,6 +201,9 @@ checkFile('src/core/security.js');
201
201
  checkFile('src/core/globals.js');
202
202
  checkFile('src/registry/validation.js');
203
203
  checkFile('src/registry/sources.js');
204
+ checkFile('src/registry/provenance.js');
205
+ checkFile('src/registry/signing.js');
206
+ checkFile('src/registry/trust-store.js');
204
207
  checkFile('src/catalog/loader.js');
205
208
  checkFile('src/plugin/manifest.js');
206
209
 
@@ -246,6 +249,8 @@ checkFile('docs/registry-contribution.md');
246
249
  checkFile('docs/v2-migration.md');
247
250
  checkFile('docs/v2-release-checklist.md');
248
251
  checkFile('docs/package-safety.md');
252
+ checkFile('docs/registry-signing.md');
253
+ checkFile('docs/registry-trust-store.md');
249
254
 
250
255
  // --- v2.1.0 Intelligence Layer Documentation ---
251
256
  console.log('\nIntelligence Layer Documentation:');
@@ -280,6 +285,7 @@ console.log('\nJSON Schemas:');
280
285
  checkFile('.ai/schema/config.schema.json');
281
286
  checkFile('.ai/schema/template.schema.json');
282
287
  checkFile('.ai/schema/adapter.schema.json');
288
+ checkFile('.ai/schema/trusted-keys.schema.json');
283
289
 
284
290
  // --- v2.1.0 Intelligence Layer (Schemas, Policies, Registries) ---
285
291
  console.log('\nIntelligence Layer Schemas:');
@@ -302,8 +308,25 @@ console.log('\nIntelligence Layer Registries:');
302
308
  checkFile('.ai/registries/capabilities.yaml');
303
309
  checkFile('.ai/registries/tools.yaml');
304
310
  checkFile('.ai/registries/workflows.yaml');
305
-
306
- // --- Test Blueprints ---
311
+ checkFile('.ai/registries/trusted-keys.yaml');
312
+
313
+ // --- Unit Tests ---
314
+ console.log('\nUnit Tests:');
315
+ checkFile('tests/unit/yaml.test.js');
316
+ checkFile('tests/unit/registry-url-validation.test.js');
317
+ checkFile('tests/unit/registry-policy.test.js');
318
+ checkFile('tests/unit/registry-provenance.test.js');
319
+ checkFile('tests/unit/registry-signing.test.js');
320
+ checkFile('tests/unit/registry-public-signing.test.js');
321
+ checkFile('tests/unit/registry-trust-store.test.js');
322
+ checkFile('tests/unit/registry-signature-policy.test.js');
323
+ checkFile('tests/unit/path-safety.test.js');
324
+ checkFile('tests/unit/plugin-manifest.test.js');
325
+ checkFile('tests/unit/catalog-loader.test.js');
326
+ checkFile('tests/unit/build-output.test.js');
327
+ checkFile('tests/unit/prepublish-guard.test.js');
328
+
329
+ // --- Test Manuals & Fixtures ---
307
330
  console.log('\nTest Manuals:');
308
331
  checkFile('tests/README.md');
309
332
  checkFile('tests/fixtures/README.md');
@@ -564,7 +587,7 @@ try {
564
587
  }
565
588
  }
566
589
 
567
- // Test 2: Allows version 3.2.0 with MMDO_ALLOW_PUBLISH=true
590
+ // Test 2: Allows version 3.5.0 with MMDO_ALLOW_PUBLISH=true
568
591
  try {
569
592
  const output = execSync('node scripts/prepublish-guard.js', {
570
593
  cwd: projectRoot,
@@ -572,7 +595,7 @@ try {
572
595
  encoding: 'utf8'
573
596
  });
574
597
  if (output.includes('Prepublish guard passed')) {
575
- console.log(` ${GREEN}✓${NC} prepublish guard allows version 3.2.0 when MMDO_ALLOW_PUBLISH=true`);
598
+ console.log(` ${GREEN}✓${NC} prepublish guard allows version 3.5.0 when MMDO_ALLOW_PUBLISH=true`);
576
599
  pass++;
577
600
  } else {
578
601
  console.error(` ${RED}✗${NC} prepublish guard passed but stdout missing success indicator`);
@@ -580,7 +603,7 @@ try {
580
603
  }
581
604
  } catch (err) {
582
605
  const errText = err.stderr ? err.stderr.toString() : '';
583
- console.error(` ${RED}✗${NC} prepublish guard blocked version 3.2.0: ${errText || err.message}`);
606
+ console.error(` ${RED}✗${NC} prepublish guard blocked version 3.5.0: ${errText || err.message}`);
584
607
  fail++;
585
608
  }
586
609
 
@@ -594,12 +617,12 @@ try {
594
617
  pass++;
595
618
  }
596
619
 
597
- // Test 4: Package.json version is exactly 3.2.0
598
- if (expectedVersion === '3.2.0') {
599
- console.log(` ${GREEN}✓${NC} package.json version is exactly 3.2.0`);
620
+ // Test 4: Package.json version is exactly 3.5.0
621
+ if (expectedVersion === '3.5.0') {
622
+ console.log(` ${GREEN}✓${NC} package.json version is exactly 3.5.0`);
600
623
  pass++;
601
624
  } else {
602
- console.error(` ${RED}✗${NC} package.json version is not 3.2.0 (found ${expectedVersion})`);
625
+ console.error(` ${RED}✗${NC} package.json version is not 3.5.0 (found ${expectedVersion})`);
603
626
  fail++;
604
627
  }
605
628
  } catch (e) {
@@ -1387,6 +1410,180 @@ const checkExamplesHygiene = (dir) => {
1387
1410
  };
1388
1411
  checkExamplesHygiene(join(projectRoot, 'examples'));
1389
1412
 
1413
+ // --- Registry Signing & Provenance Checks ---
1414
+ console.log('\nRegistry Signing & Provenance Checks:');
1415
+
1416
+ // Check .gitignore contains registry-signing-key
1417
+ try {
1418
+ const gitignoreContent = readFileSync(join(projectRoot, '.gitignore'), 'utf8');
1419
+ if (gitignoreContent.includes('registry-signing-key')) {
1420
+ console.log(` ${GREEN}✓${NC} .gitignore includes registry-signing-key pattern`);
1421
+ pass++;
1422
+ } else {
1423
+ console.error(` ${RED}✗${NC} .gitignore is missing the registry-signing-key entry (secrets must be gitignored)`);
1424
+ fail++;
1425
+ }
1426
+ } catch (e) {
1427
+ console.error(` ${RED}✗${NC} Failed to read .gitignore: ${e.message}`);
1428
+ fail++;
1429
+ }
1430
+
1431
+ // Check provenance.js exports the expected API surface
1432
+ try {
1433
+ const provenanceSrc = readFileSync(join(projectRoot, 'src', 'registry', 'provenance.js'), 'utf8');
1434
+ const hasLoadLockfile = provenanceSrc.includes('export function loadRegistryLockfile');
1435
+ const hasSaveLockfile = provenanceSrc.includes('export function saveRegistryLockfile');
1436
+ const hasUpdateEntry = provenanceSrc.includes('export function updateLockfileEntry');
1437
+ const hasGetPath = provenanceSrc.includes('export function getLockfilePath');
1438
+ if (hasLoadLockfile && hasSaveLockfile && hasUpdateEntry && hasGetPath) {
1439
+ console.log(` ${GREEN}✓${NC} src/registry/provenance.js exports complete API (load/save/update/getPath)`);
1440
+ pass++;
1441
+ } else {
1442
+ console.error(` ${RED}✗${NC} src/registry/provenance.js is missing expected exports`);
1443
+ fail++;
1444
+ }
1445
+ } catch (e) {
1446
+ console.error(` ${RED}✗${NC} Failed to check provenance.js: ${e.message}`);
1447
+ fail++;
1448
+ }
1449
+
1450
+ // Check signing.js exports the expected API surface
1451
+ try {
1452
+ const signingSrc = readFileSync(join(projectRoot, 'src', 'registry', 'signing.js'), 'utf8');
1453
+ const hasLoadKey = signingSrc.includes('export function loadSigningKey');
1454
+ const hasGenKey = signingSrc.includes('export function generateSigningKey');
1455
+ const hasSaveKey = signingSrc.includes('export function saveSigningKey');
1456
+ const hasSign = signingSrc.includes('export function signPayload');
1457
+ const hasVerify = signingSrc.includes('export function verifySignature');
1458
+ const hasTimingSafe = signingSrc.includes('timingSafeEqual');
1459
+ const hasEdKeygen = signingSrc.includes('export function generateEd25519KeyPair');
1460
+ const hasEdSign = signingSrc.includes('export function signEd25519Payload');
1461
+ const hasEdVerify = signingSrc.includes('export function verifyEd25519Payload');
1462
+ const hasSigBlockVerify = signingSrc.includes('export function verifySignatureBlock');
1463
+
1464
+ if (hasLoadKey && hasGenKey && hasSaveKey && hasSign && hasVerify && hasTimingSafe && hasEdKeygen && hasEdSign && hasEdVerify && hasSigBlockVerify) {
1465
+ console.log(` ${GREEN}✓${NC} src/registry/signing.js exports complete API (HMAC + Ed25519)`);
1466
+ pass++;
1467
+ } else {
1468
+ console.error(` ${RED}✗${NC} src/registry/signing.js is missing expected exports`);
1469
+ fail++;
1470
+ }
1471
+ } catch (e) {
1472
+ console.error(` ${RED}✗${NC} Failed to check signing.js: ${e.message}`);
1473
+ fail++;
1474
+ }
1475
+
1476
+ // Check trust-store.js exports expected API surface
1477
+ try {
1478
+ const trustSrc = readFileSync(join(projectRoot, 'src', 'registry', 'trust-store.js'), 'utf8');
1479
+ const hasLoadTrustedKeys = trustSrc.includes('export function loadTrustedKeys');
1480
+ if (hasLoadTrustedKeys) {
1481
+ console.log(` ${GREEN}✓${NC} src/registry/trust-store.js exports loadTrustedKeys`);
1482
+ pass++;
1483
+ } else {
1484
+ console.error(` ${RED}✗${NC} src/registry/trust-store.js is missing expected exports`);
1485
+ fail++;
1486
+ }
1487
+ } catch (e) {
1488
+ console.error(` ${RED}✗${NC} Failed to check trust-store.js: ${e.message}`);
1489
+ fail++;
1490
+ }
1491
+
1492
+ // Check main.js imports the new modules
1493
+ try {
1494
+ const mainSrc = readFileSync(join(projectRoot, 'src', 'cli', 'main.js'), 'utf8');
1495
+ const hasProvenanceImport = mainSrc.includes("from '../registry/provenance.js'");
1496
+ const hasSigningImport = mainSrc.includes("from '../registry/signing.js'");
1497
+ const hasTrustImport = mainSrc.includes("from '../registry/trust-store.js'");
1498
+ const hasKeygenHandler = mainSrc.includes('handleRegistryKeygen');
1499
+ const hasLockHandler = mainSrc.includes('handleRegistryLock');
1500
+ const hasTrustHandler = mainSrc.includes('handleRegistryTrustList');
1501
+ if (hasProvenanceImport && hasSigningImport && hasTrustImport && hasKeygenHandler && hasLockHandler && hasTrustHandler) {
1502
+ console.log(` ${GREEN}✓${NC} src/cli/main.js imports provenance/signing/trust-store and registers handlers`);
1503
+ pass++;
1504
+ } else {
1505
+ console.error(` ${RED}✗${NC} src/cli/main.js is missing required imports or handlers`);
1506
+ fail++;
1507
+ }
1508
+ } catch (e) {
1509
+ console.error(` ${RED}✗${NC} Failed to check main.js integrations: ${e.message}`);
1510
+ fail++;
1511
+ }
1512
+
1513
+ // Check that policy.js has the new fields in defaults
1514
+ try {
1515
+ const policySrc = readFileSync(join(projectRoot, 'src', 'core', 'policy.js'), 'utf8');
1516
+ const hasLockfileField = policySrc.includes('require_lockfile_on_verify');
1517
+ const hasUnsignedLocal = policySrc.includes('allow_unsigned_local');
1518
+ const hasUnsignedBundled = policySrc.includes('allow_unsigned_bundled');
1519
+ const hasUnsignedRemote = policySrc.includes('allow_unsigned_remote');
1520
+ const hasTrustedKeysFile = policySrc.includes('trusted_keys_file');
1521
+ const hasAllowedAlgs = policySrc.includes('allowed_signature_algorithms');
1522
+ const hasRequireTrustedPublisher = policySrc.includes('require_trusted_publisher');
1523
+ const hasProvenanceRequired = policySrc.includes('provenance_required');
1524
+
1525
+ if (hasLockfileField && hasUnsignedLocal && hasUnsignedBundled && hasUnsignedRemote && hasTrustedKeysFile && hasAllowedAlgs && hasRequireTrustedPublisher && hasProvenanceRequired) {
1526
+ console.log(` ${GREEN}✓${NC} src/core/policy.js includes all Sprint 2 policy defaults`);
1527
+ pass++;
1528
+ } else {
1529
+ console.error(` ${RED}✗${NC} src/core/policy.js is missing required policy defaults`);
1530
+ fail++;
1531
+ }
1532
+ } catch (e) {
1533
+ console.error(` ${RED}✗${NC} Failed to check policy.js: ${e.message}`);
1534
+ fail++;
1535
+ }
1536
+
1537
+ // --- v3.5.0 Sprint 3 E2E Fixtures & Threat Model Checks ---
1538
+ console.log('\nSprint 3 Signed Registry E2E & Readiness Checks:');
1539
+ checkFile('src/registry/verdict.js');
1540
+ checkFile('tests/unit/registry-e2e-signature-fixtures.test.js');
1541
+ checkFile('docs/security-threat-model.md');
1542
+ checkFile('docs/v3.5.0-readiness.md');
1543
+
1544
+ // Verify that the trusted-keys.yaml in the E2E fixtures directory exists
1545
+ const e2eKeysPath = 'tests/fixtures/signed-registries/trusted-keys.yaml';
1546
+ if (checkFile(e2eKeysPath)) {
1547
+ const e2eKeysContent = readFileSync(join(projectRoot, e2eKeysPath), 'utf8');
1548
+ if (e2eKeysContent.includes('test-key-valid') && e2eKeysContent.includes('test-key-revoked')) {
1549
+ console.log(` ${GREEN}✓${NC} ${e2eKeysPath} is populated with test fixtures and marked for testing`);
1550
+ pass++;
1551
+ } else {
1552
+ console.error(` ${RED}✗${NC} ${e2eKeysPath} is missing expected test keys`);
1553
+ fail++;
1554
+ }
1555
+ }
1556
+
1557
+ // Verify that the threat model document has a standard threat modeling structure
1558
+ try {
1559
+ const threatModelContent = readFileSync(join(projectRoot, 'docs/security-threat-model.md'), 'utf8');
1560
+ if (threatModelContent.includes('Threat Model') && (threatModelContent.includes('STRIDE') || threatModelContent.includes('stride'))) {
1561
+ console.log(` ${GREEN}✓${NC} docs/security-threat-model.md structure verified`);
1562
+ pass++;
1563
+ } else {
1564
+ console.error(` ${RED}✗${NC} docs/security-threat-model.md is missing standard threat modeling structure`);
1565
+ fail++;
1566
+ }
1567
+ } catch (e) {
1568
+ console.error(` ${RED}✗${NC} Failed to verify threat model document: ${e.message}`);
1569
+ fail++;
1570
+ }
1571
+
1572
+ // Verify that no private keys are committed in main directories (like .ai/)
1573
+ try {
1574
+ const rootKeyFile = '.ai/registry-signing-key';
1575
+ if (existsSync(join(projectRoot, rootKeyFile))) {
1576
+ console.error(` ${RED}✗${NC} Private signing key ${rootKeyFile} should not be committed!`);
1577
+ fail++;
1578
+ } else {
1579
+ console.log(` ${GREEN}✓${NC} No private registry-signing-key found in codebase root`);
1580
+ pass++;
1581
+ }
1582
+ } catch (e) {
1583
+ console.error(` ${RED}✗${NC} Failed to check private key existence: ${e.message}`);
1584
+ fail++;
1585
+ }
1586
+
1390
1587
  console.log('\n=====================================================');
1391
1588
  const total = pass + fail + warn;
1392
1589
  console.log(` Pass: ${GREEN}${pass}${NC} Fail: ${RED}${fail}${NC} Warn: ${YELLOW}${warn}${NC} Total: ${total}`);
package/src/cli/help.js CHANGED
@@ -18,7 +18,7 @@ export function showHelp() {
18
18
  console.log(' adapter <subcmd> Manage and sync rule/settings files for IDE adapters (subcmd: status, diff, sync)');
19
19
  console.log(' plugin <subcmd> Manage declarative plugins (subcmd: list, show, validate, install, status)');
20
20
  console.log(' catalog <subcmd> Manage Workflow Marketplace & Plugin Catalog (subcmd: list, search, show, categories, recommend, install, status)');
21
- console.log(' registry <subcmd> Manage trusted remote catalog registries (subcmd: list, add, remove, sync, status, verify, show, cache)');
21
+ console.log(' registry <subcmd> Manage trusted remote catalog registries (subcmd: list, add, remove, sync, status, verify, show, cache, keygen, lock, trust)');
22
22
  console.log(' verify Validate structural integrity of an existing project');
23
23
  console.log(' templates List all built-in template profiles with details');
24
24
  console.log(' list-templates Alias for templates command');