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.
- package/.ai/policies/registry-policy.yaml +29 -1
- package/.ai/registries/trusted-keys.yaml +12 -0
- package/.ai/schema/registry-manifest.schema.json +31 -2
- package/.ai/schema/registry-policy.schema.json +37 -1
- package/.ai/schema/trusted-keys.schema.json +69 -0
- package/AGENTS.md +22 -26
- package/MEMORY.md +34 -11
- package/README.md +1 -1
- package/RUNBOOK.md +28 -36
- package/TASKS.md +15 -5
- package/bin/multimodel-dev-os.js +1366 -548
- package/docs/.vitepress/config.js +3 -1
- package/docs/architecture.md +3 -1
- package/docs/index.md +5 -5
- package/docs/npm-publishing.md +5 -5
- package/docs/package-safety.md +3 -2
- package/docs/public/llms-full.txt +5 -1
- package/docs/public/llms.txt +6 -1
- package/docs/public/sitemap.xml +10 -0
- package/docs/registry-policy.md +29 -1
- package/docs/registry-security.md +73 -6
- package/docs/registry-signing.md +70 -0
- package/docs/registry-sync.md +5 -2
- package/docs/registry-trust-store.md +66 -0
- package/docs/release-policy.md +1 -1
- package/docs/security-threat-model.md +96 -0
- package/docs/testing.md +15 -2
- package/docs/trusted-registries.md +1 -1
- package/docs/v3-roadmap.md +11 -6
- package/docs/v3.5.0-readiness.md +46 -0
- package/package.json +1 -1
- package/scripts/install.ps1 +1 -1
- package/scripts/install.sh +1 -1
- package/scripts/verify.js +206 -9
- package/src/cli/help.js +1 -1
- package/src/cli/main.js +626 -81
- package/src/core/policy.js +9 -1
- package/src/registry/provenance.js +114 -0
- package/src/registry/signing.js +392 -0
- package/src/registry/trust-store.js +41 -0
- package/src/registry/verdict.js +51 -0
- package/tests/fixtures/signed-registries/README.md +4 -0
- package/tests/fixtures/signed-registries/revoked-key/catalog.yaml +8 -0
- package/tests/fixtures/signed-registries/revoked-key/expected-verdict.json +7 -0
- package/tests/fixtures/signed-registries/revoked-key/registry-manifest.yaml +14 -0
- package/tests/fixtures/signed-registries/tampered-manifest/catalog.yaml +8 -0
- package/tests/fixtures/signed-registries/tampered-manifest/expected-verdict.json +7 -0
- package/tests/fixtures/signed-registries/tampered-manifest/registry-manifest.yaml +14 -0
- package/tests/fixtures/signed-registries/trusted-keys.yaml +23 -0
- package/tests/fixtures/signed-registries/unsigned-remote-required/catalog.yaml +8 -0
- package/tests/fixtures/signed-registries/unsigned-remote-required/expected-verdict.json +7 -0
- package/tests/fixtures/signed-registries/unsigned-remote-required/registry-manifest.yaml +9 -0
- package/tests/fixtures/signed-registries/unsupported-algorithm/catalog.yaml +8 -0
- package/tests/fixtures/signed-registries/unsupported-algorithm/expected-verdict.json +7 -0
- package/tests/fixtures/signed-registries/unsupported-algorithm/registry-manifest.yaml +14 -0
- package/tests/fixtures/signed-registries/valid-signed-registry/catalog.yaml +8 -0
- package/tests/fixtures/signed-registries/valid-signed-registry/expected-verdict.json +7 -0
- package/tests/fixtures/signed-registries/valid-signed-registry/registry-manifest.yaml +14 -0
- package/tests/fixtures/signed-registries/wrong-key/catalog.yaml +8 -0
- package/tests/fixtures/signed-registries/wrong-key/expected-verdict.json +7 -0
- package/tests/fixtures/signed-registries/wrong-key/registry-manifest.yaml +14 -0
- package/tests/unit/registry-e2e-signature-fixtures.test.js +288 -0
- package/tests/unit/registry-policy.test.js +6 -0
- package/tests/unit/registry-provenance.test.js +185 -0
- package/tests/unit/registry-public-signing.test.js +109 -0
- package/tests/unit/registry-signature-policy.test.js +100 -0
- package/tests/unit/registry-signing.test.js +193 -0
- package/tests/unit/registry-trust-store.test.js +133 -0
package/docs/v3-roadmap.md
CHANGED
|
@@ -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.
|
|
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.
|
|
84
|
-
|
|
85
|
-
|
|
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
package/scripts/install.ps1
CHANGED
package/scripts/install.sh
CHANGED
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
598
|
-
if (expectedVersion === '3.
|
|
599
|
-
console.log(` ${GREEN}✓${NC} package.json version is exactly 3.
|
|
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.
|
|
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');
|