chainlesschain 0.47.9 → 0.49.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 (70) hide show
  1. package/bin/chainlesschain.js +0 -0
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/.build-hash +1 -1
  4. package/src/assets/web-panel/assets/{AppLayout-6SPt_8Y_.js → AppLayout-Rvi759IS.js} +1 -1
  5. package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +1 -0
  6. package/src/assets/web-panel/assets/{Dashboard-Br7kCwKJ.js → Dashboard-DBhFxXYQ.js} +2 -2
  7. package/src/assets/web-panel/assets/{index-tN-8TosE.js → index-uL0cZ8N_.js} +2 -2
  8. package/src/assets/web-panel/index.html +2 -2
  9. package/src/commands/codegen.js +303 -0
  10. package/src/commands/collab.js +482 -0
  11. package/src/commands/crosschain.js +382 -0
  12. package/src/commands/dbevo.js +388 -0
  13. package/src/commands/dev.js +411 -0
  14. package/src/commands/federation.js +427 -0
  15. package/src/commands/fusion.js +332 -0
  16. package/src/commands/governance.js +505 -0
  17. package/src/commands/hardening.js +110 -0
  18. package/src/commands/incentive.js +373 -0
  19. package/src/commands/inference.js +304 -0
  20. package/src/commands/infra.js +361 -0
  21. package/src/commands/kg.js +371 -0
  22. package/src/commands/marketplace.js +326 -0
  23. package/src/commands/mcp.js +97 -18
  24. package/src/commands/nlprog.js +329 -0
  25. package/src/commands/ops.js +408 -0
  26. package/src/commands/perception.js +385 -0
  27. package/src/commands/pqc.js +34 -0
  28. package/src/commands/privacy.js +345 -0
  29. package/src/commands/quantization.js +280 -0
  30. package/src/commands/recommend.js +336 -0
  31. package/src/commands/reputation.js +349 -0
  32. package/src/commands/runtime.js +500 -0
  33. package/src/commands/sla.js +352 -0
  34. package/src/commands/stress.js +252 -0
  35. package/src/commands/tech.js +268 -0
  36. package/src/commands/tenant.js +576 -0
  37. package/src/commands/trust.js +366 -0
  38. package/src/harness/mcp-client.js +330 -54
  39. package/src/index.js +112 -0
  40. package/src/lib/aiops.js +523 -0
  41. package/src/lib/autonomous-developer.js +524 -0
  42. package/src/lib/code-agent.js +442 -0
  43. package/src/lib/collaboration-governance.js +556 -0
  44. package/src/lib/community-governance.js +649 -0
  45. package/src/lib/content-recommendation.js +600 -0
  46. package/src/lib/cross-chain.js +669 -0
  47. package/src/lib/dbevo.js +669 -0
  48. package/src/lib/decentral-infra.js +445 -0
  49. package/src/lib/federation-hardening.js +587 -0
  50. package/src/lib/hardening-manager.js +409 -0
  51. package/src/lib/inference-network.js +407 -0
  52. package/src/lib/knowledge-graph.js +530 -0
  53. package/src/lib/mcp-client.js +3 -0
  54. package/src/lib/multimodal.js +698 -0
  55. package/src/lib/nl-programming.js +595 -0
  56. package/src/lib/perception.js +500 -0
  57. package/src/lib/pqc-manager.js +141 -9
  58. package/src/lib/privacy-computing.js +575 -0
  59. package/src/lib/protocol-fusion.js +535 -0
  60. package/src/lib/quantization.js +362 -0
  61. package/src/lib/reputation-optimizer.js +509 -0
  62. package/src/lib/skill-marketplace.js +397 -0
  63. package/src/lib/sla-manager.js +484 -0
  64. package/src/lib/stress-tester.js +383 -0
  65. package/src/lib/tech-learning-engine.js +651 -0
  66. package/src/lib/tenant-saas.js +831 -0
  67. package/src/lib/token-incentive.js +513 -0
  68. package/src/lib/trust-security.js +473 -0
  69. package/src/lib/universal-runtime.js +771 -0
  70. package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +0 -1
@@ -4,11 +4,33 @@
4
4
  */
5
5
 
6
6
  import crypto from "crypto";
7
+ import fs from "fs";
8
+ import path from "path";
9
+
10
+ /* ── Dependency injection (for tests) ─────────────────────── */
11
+ const _deps = { fs, path };
12
+ export { _deps };
7
13
 
8
14
  /* ── In-memory stores ──────────────────────────────────────── */
9
15
  const _baselines = new Map();
10
16
  const _audits = new Map();
11
17
 
18
+ /* ── Config audit constants ────────────────────────────────── */
19
+
20
+ const DEFAULT_FORBIDDEN_PLACEHOLDERS = [
21
+ "changeme",
22
+ "change-me",
23
+ "your-api-key",
24
+ "your-secret",
25
+ "xxx",
26
+ "todo",
27
+ "replace-me",
28
+ ];
29
+
30
+ const DEFAULT_REQUIRED_KEYS = []; // caller-supplied; empty default keeps helper generic
31
+
32
+ const CONFIG_CHECK_PREFIX = "config:";
33
+
12
34
  const BASELINE_STATUS = {
13
35
  COLLECTING: "collecting",
14
36
  COMPLETE: "complete",
@@ -267,6 +289,393 @@ export function getAuditReport(auditId) {
267
289
  return audit;
268
290
  }
269
291
 
292
+ /* ── Config Audit (real, deterministic) ───────────────────── */
293
+
294
+ /**
295
+ * Load a JSON config file from disk. Returns `null` if missing or unreadable.
296
+ * Throws `SyntaxError` on malformed JSON so callers can distinguish
297
+ * "file not present" (checklist: absent) from "file invalid" (checklist: fail).
298
+ */
299
+ export function loadConfig(configPath) {
300
+ if (!configPath) return null;
301
+ if (!_deps.fs.existsSync(configPath)) return null;
302
+ const raw = _deps.fs.readFileSync(configPath, "utf-8");
303
+ return JSON.parse(raw);
304
+ }
305
+
306
+ function _getByPath(obj, keyPath) {
307
+ if (obj == null) return undefined;
308
+ const parts = keyPath.split(".");
309
+ let cur = obj;
310
+ for (const p of parts) {
311
+ if (cur == null || typeof cur !== "object") return undefined;
312
+ cur = cur[p];
313
+ }
314
+ return cur;
315
+ }
316
+
317
+ function _containsPlaceholder(value, placeholders) {
318
+ if (typeof value !== "string") return null;
319
+ const lower = value.toLowerCase();
320
+ for (const ph of placeholders) {
321
+ if (lower.includes(ph.toLowerCase())) return ph;
322
+ }
323
+ return null;
324
+ }
325
+
326
+ /**
327
+ * Pure config inspection. Accepts a parsed config object (or null when the
328
+ * file is absent) and returns a check list.
329
+ *
330
+ * opts.configPath — reporting only (used in detail messages)
331
+ * opts.requiredKeys — dot-paths that MUST be present and non-empty
332
+ * opts.forbiddenPlaceholders — substrings that disqualify a string value
333
+ * (defaults to common "changeme" style)
334
+ * opts.dangerousDefaults — [{path, badValue}] — path MUST NOT equal badValue
335
+ */
336
+ export function checkConfig(config, opts = {}) {
337
+ const {
338
+ configPath = "(inline)",
339
+ requiredKeys = DEFAULT_REQUIRED_KEYS,
340
+ forbiddenPlaceholders = DEFAULT_FORBIDDEN_PLACEHOLDERS,
341
+ dangerousDefaults = [],
342
+ } = opts;
343
+
344
+ const checks = [];
345
+
346
+ // File presence
347
+ checks.push(
348
+ config == null
349
+ ? {
350
+ name: "config.file_present",
351
+ status: "fail",
352
+ severity: "high",
353
+ detail: `Config file not found: ${configPath}`,
354
+ }
355
+ : {
356
+ name: "config.file_present",
357
+ status: "pass",
358
+ severity: "info",
359
+ detail: `Loaded ${configPath}`,
360
+ },
361
+ );
362
+
363
+ if (config != null) {
364
+ // Required keys
365
+ for (const key of requiredKeys) {
366
+ const val = _getByPath(config, key);
367
+ const missing = val === undefined || val === null || val === "";
368
+ checks.push({
369
+ name: `config.required.${key}`,
370
+ status: missing ? "fail" : "pass",
371
+ severity: missing ? "high" : "info",
372
+ detail: missing
373
+ ? `Required key missing or empty: ${key}`
374
+ : `Present: ${key}`,
375
+ });
376
+ }
377
+
378
+ // Placeholder scan — recurse through string values
379
+ const offenders = [];
380
+ const scan = (val, trail) => {
381
+ if (val == null) return;
382
+ if (typeof val === "string") {
383
+ const hit = _containsPlaceholder(val, forbiddenPlaceholders);
384
+ if (hit) offenders.push({ path: trail, placeholder: hit });
385
+ return;
386
+ }
387
+ if (typeof val !== "object") return;
388
+ for (const [k, v] of Object.entries(val)) {
389
+ scan(v, trail ? `${trail}.${k}` : k);
390
+ }
391
+ };
392
+ scan(config, "");
393
+ if (offenders.length === 0) {
394
+ checks.push({
395
+ name: "config.no_placeholders",
396
+ status: "pass",
397
+ severity: "info",
398
+ detail: "No placeholder values detected",
399
+ });
400
+ } else {
401
+ for (const o of offenders) {
402
+ checks.push({
403
+ name: `config.placeholder.${o.path}`,
404
+ status: "fail",
405
+ severity: "critical",
406
+ detail: `Placeholder "${o.placeholder}" at ${o.path}`,
407
+ });
408
+ }
409
+ }
410
+
411
+ // Dangerous default detection
412
+ for (const { path: p, badValue } of dangerousDefaults) {
413
+ const val = _getByPath(config, p);
414
+ const dangerous = val === badValue;
415
+ checks.push({
416
+ name: `config.dangerous_default.${p}`,
417
+ status: dangerous ? "fail" : "pass",
418
+ severity: dangerous ? "high" : "info",
419
+ detail: dangerous
420
+ ? `${p} still at dangerous default (${JSON.stringify(badValue)})`
421
+ : `${p} overridden`,
422
+ });
423
+ }
424
+ }
425
+
426
+ const passed = checks.filter((c) => c.status === "pass").length;
427
+ const failed = checks.length - passed;
428
+ const score = checks.length ? Math.round((passed / checks.length) * 100) : 0;
429
+
430
+ return { checks, passed, failed, score, configPath };
431
+ }
432
+
433
+ /**
434
+ * Run a config audit and persist it to `hardening_audits`. Audit name is
435
+ * prefixed with `CONFIG_CHECK_PREFIX` so `deployCheck` can locate it.
436
+ */
437
+ export function runConfigAudit(db, opts = {}) {
438
+ const {
439
+ name = "default",
440
+ configPath,
441
+ requiredKeys,
442
+ forbiddenPlaceholders,
443
+ dangerousDefaults,
444
+ } = opts;
445
+ if (!configPath) throw new Error("configPath is required");
446
+
447
+ let config = null;
448
+ let loadError = null;
449
+ try {
450
+ config = loadConfig(configPath);
451
+ } catch (err) {
452
+ loadError = err;
453
+ }
454
+
455
+ const result =
456
+ loadError != null
457
+ ? {
458
+ checks: [
459
+ {
460
+ name: "config.file_parseable",
461
+ status: "fail",
462
+ severity: "critical",
463
+ detail: `Failed to parse ${configPath}: ${loadError.message}`,
464
+ },
465
+ ],
466
+ passed: 0,
467
+ failed: 1,
468
+ score: 0,
469
+ configPath,
470
+ }
471
+ : checkConfig(config, {
472
+ configPath,
473
+ requiredKeys,
474
+ forbiddenPlaceholders,
475
+ dangerousDefaults,
476
+ });
477
+
478
+ const id = crypto.randomUUID();
479
+ const now = new Date().toISOString();
480
+ const recommendations = result.checks
481
+ .filter((c) => c.status === "fail")
482
+ .map((c) => `Fix [${c.severity || "medium"}]: ${c.name} — ${c.detail}`);
483
+
484
+ const audit = {
485
+ id,
486
+ name: `${CONFIG_CHECK_PREFIX}${name}`,
487
+ checks: result.checks,
488
+ passed: result.passed,
489
+ failed: result.failed,
490
+ score: result.score,
491
+ recommendations,
492
+ configPath,
493
+ createdAt: now,
494
+ };
495
+
496
+ _audits.set(id, audit);
497
+
498
+ db.prepare(
499
+ `INSERT INTO hardening_audits (id, name, checks, passed, failed, score, recommendations, created_at)
500
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
501
+ ).run(
502
+ id,
503
+ audit.name,
504
+ JSON.stringify(result.checks),
505
+ result.passed,
506
+ result.failed,
507
+ result.score,
508
+ JSON.stringify(recommendations),
509
+ now,
510
+ );
511
+
512
+ return audit;
513
+ }
514
+
515
+ /* ── Deployment Readiness Check ───────────────────────────── */
516
+
517
+ function _severityCounts(checks) {
518
+ const counts = { critical: 0, high: 0, medium: 0, low: 0, info: 0 };
519
+ for (const c of checks || []) {
520
+ if (c.status !== "fail") continue;
521
+ const sev = c.severity || "medium";
522
+ if (counts[sev] != null) counts[sev]++;
523
+ }
524
+ return counts;
525
+ }
526
+
527
+ /**
528
+ * Evaluate the six "§八 部署检查清单" items against the current
529
+ * `_baselines` / `_audits` stores.
530
+ *
531
+ * Returns `{ ready, items[], summary }` where each item is
532
+ * `{ id, label, status: "pass"|"fail"|"skipped", detail }`.
533
+ *
534
+ * CLI-evaluable items:
535
+ * - baseline_established — any baseline in store
536
+ * - security_audit_score_80 — latest non-config audit score >= 80
537
+ * - no_critical_high_vulns — latest non-config audit: 0 critical + 0 high fails
538
+ * - config_items_checked — latest config:* audit has score >= 80
539
+ *
540
+ * Desktop-only items (reported as skipped):
541
+ * - alerting_tested, monitoring_dashboard
542
+ */
543
+ export function deployCheck() {
544
+ const baselines = [..._baselines.values()];
545
+ const audits = [..._audits.values()];
546
+ const configAudits = audits.filter((a) =>
547
+ (a.name || "").startsWith(CONFIG_CHECK_PREFIX),
548
+ );
549
+ const nonConfigAudits = audits.filter(
550
+ (a) => !(a.name || "").startsWith(CONFIG_CHECK_PREFIX),
551
+ );
552
+
553
+ const latestBy = (arr) =>
554
+ arr.length === 0
555
+ ? null
556
+ : arr.reduce((a, b) => (a.createdAt > b.createdAt ? a : b));
557
+
558
+ const latestAudit = latestBy(nonConfigAudits);
559
+ const latestConfigAudit = latestBy(configAudits);
560
+
561
+ const items = [];
562
+
563
+ items.push(
564
+ baselines.length > 0
565
+ ? {
566
+ id: "baseline_established",
567
+ label: "性能基线已建立",
568
+ status: "pass",
569
+ detail: `${baselines.length} baseline(s) recorded`,
570
+ }
571
+ : {
572
+ id: "baseline_established",
573
+ label: "性能基线已建立",
574
+ status: "fail",
575
+ detail:
576
+ "No baseline collected — run `cc hardening baseline collect <name>`",
577
+ },
578
+ );
579
+
580
+ items.push(
581
+ latestAudit == null
582
+ ? {
583
+ id: "security_audit_score_80",
584
+ label: "安全审计已完成且评分 >= 80",
585
+ status: "fail",
586
+ detail: "No security audit has been run",
587
+ }
588
+ : latestAudit.score >= 80
589
+ ? {
590
+ id: "security_audit_score_80",
591
+ label: "安全审计已完成且评分 >= 80",
592
+ status: "pass",
593
+ detail: `Latest audit "${latestAudit.name}" score=${latestAudit.score}%`,
594
+ }
595
+ : {
596
+ id: "security_audit_score_80",
597
+ label: "安全审计已完成且评分 >= 80",
598
+ status: "fail",
599
+ detail: `Latest audit score ${latestAudit.score}% < 80`,
600
+ },
601
+ );
602
+
603
+ if (latestAudit == null) {
604
+ items.push({
605
+ id: "no_critical_high_vulns",
606
+ label: "无 CRITICAL 和 HIGH 级别漏洞",
607
+ status: "fail",
608
+ detail: "No audit to evaluate severities",
609
+ });
610
+ } else {
611
+ const sev = _severityCounts(latestAudit.checks);
612
+ const bad = sev.critical + sev.high;
613
+ items.push(
614
+ bad === 0
615
+ ? {
616
+ id: "no_critical_high_vulns",
617
+ label: "无 CRITICAL 和 HIGH 级别漏洞",
618
+ status: "pass",
619
+ detail: `critical=0 high=0 (medium=${sev.medium} low=${sev.low})`,
620
+ }
621
+ : {
622
+ id: "no_critical_high_vulns",
623
+ label: "无 CRITICAL 和 HIGH 级别漏洞",
624
+ status: "fail",
625
+ detail: `critical=${sev.critical} high=${sev.high}`,
626
+ },
627
+ );
628
+ }
629
+
630
+ items.push(
631
+ latestConfigAudit == null
632
+ ? {
633
+ id: "config_items_checked",
634
+ label: "所有配置项已检查",
635
+ status: "fail",
636
+ detail:
637
+ "No config audit has been run — use `cc hardening config-check`",
638
+ }
639
+ : latestConfigAudit.score >= 80
640
+ ? {
641
+ id: "config_items_checked",
642
+ label: "所有配置项已检查",
643
+ status: "pass",
644
+ detail: `Config audit "${latestConfigAudit.name}" score=${latestConfigAudit.score}%`,
645
+ }
646
+ : {
647
+ id: "config_items_checked",
648
+ label: "所有配置项已检查",
649
+ status: "fail",
650
+ detail: `Config audit score ${latestConfigAudit.score}% < 80`,
651
+ },
652
+ );
653
+
654
+ items.push({
655
+ id: "alerting_tested",
656
+ label: "告警机制已测试",
657
+ status: "skipped",
658
+ detail: "Desktop-only (alert UI + notification subsystem)",
659
+ });
660
+
661
+ items.push({
662
+ id: "monitoring_dashboard",
663
+ label: "监控仪表板已配置",
664
+ status: "skipped",
665
+ detail: "Desktop-only (Ant Design chart dashboard)",
666
+ });
667
+
668
+ const blocking = items.filter((i) => i.status === "fail");
669
+ const skipped = items.filter((i) => i.status === "skipped");
670
+ const passed = items.filter((i) => i.status === "pass");
671
+
672
+ return {
673
+ ready: blocking.length === 0,
674
+ items,
675
+ summary: `${passed.length} pass, ${blocking.length} fail, ${skipped.length} skipped (desktop-only)`,
676
+ };
677
+ }
678
+
270
679
  /* ── Reset (for testing) ───────────────────────────────────── */
271
680
 
272
681
  export function _resetState() {