claude-flow 3.6.25 → 3.6.26

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow",
3
- "version": "3.6.25",
3
+ "version": "3.6.26",
4
4
  "description": "Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -8,8 +8,11 @@ import { output } from '../output.js';
8
8
  import { existsSync, readFileSync, statSync } from 'fs';
9
9
  import { join, dirname } from 'path';
10
10
  import { fileURLToPath } from 'url';
11
+ import { createHash } from 'crypto';
11
12
  import { execSync, exec } from 'child_process';
12
13
  import { promisify } from 'util';
14
+ import { decodeKey, isEncryptionEnabled } from '../encryption/vault.js';
15
+ import { isEncryptedBlob } from '../encryption/vault.js';
13
16
  // Promisified exec with proper shell and env inheritance for cross-platform support
14
17
  const execAsync = promisify(exec);
15
18
  /**
@@ -423,6 +426,89 @@ async function checkAgenticFlow() {
423
426
  return { name: 'agentic-flow', status: 'warn', message: 'Check failed' };
424
427
  }
425
428
  }
429
+ // Check encryption-at-rest status (ADR-096 Phase 5)
430
+ //
431
+ // Reports four facets without disclosing the key itself:
432
+ // 1. Gate status — is CLAUDE_FLOW_ENCRYPT_AT_REST set?
433
+ // 2. Key resolution — does CLAUDE_FLOW_ENCRYPTION_KEY resolve to a valid
434
+ // 32-byte key (env-var path only; keychain/passphrase are deferred)?
435
+ // 3. Key fingerprint — first 16 hex chars of sha256(key) so users can
436
+ // sanity-check across machines without ever logging the key bytes.
437
+ // 4. High-tier store presence — for sessions/, terminals/, .swarm/memory.db
438
+ // report whether on-disk bytes carry the RFE1 magic (encrypted) or not.
439
+ async function checkEncryptionAtRest() {
440
+ if (!isEncryptionEnabled()) {
441
+ return {
442
+ name: 'Encryption at Rest',
443
+ status: 'warn',
444
+ message: 'Off — session/terminal/memory stores are plaintext (mode 0600 only)',
445
+ fix: 'export CLAUDE_FLOW_ENCRYPT_AT_REST=1 && export CLAUDE_FLOW_ENCRYPTION_KEY=<64-char-hex>',
446
+ };
447
+ }
448
+ // Gate is on — try to resolve the key. Fail-closed if missing or malformed.
449
+ const rawKey = process.env.CLAUDE_FLOW_ENCRYPTION_KEY;
450
+ if (!rawKey) {
451
+ return {
452
+ name: 'Encryption at Rest',
453
+ status: 'fail',
454
+ message: 'Gate is on but CLAUDE_FLOW_ENCRYPTION_KEY is unset (fail-closed)',
455
+ fix: 'Generate a key: openssl rand -hex 32 → export CLAUDE_FLOW_ENCRYPTION_KEY=<value>',
456
+ };
457
+ }
458
+ let keyFingerprint;
459
+ try {
460
+ const key = decodeKey(rawKey);
461
+ keyFingerprint = createHash('sha256').update(key).digest('hex').slice(0, 16);
462
+ }
463
+ catch (err) {
464
+ return {
465
+ name: 'Encryption at Rest',
466
+ status: 'fail',
467
+ message: `CLAUDE_FLOW_ENCRYPTION_KEY invalid: ${err instanceof Error ? err.message : String(err)}`,
468
+ fix: 'Provide a 64-char hex or 44-char base64 key (32 bytes)',
469
+ };
470
+ }
471
+ // Check the three high-tier store paths for RFE1 magic
472
+ const cwd = process.cwd();
473
+ const stores = [
474
+ { label: 'sessions/', path: join(cwd, '.claude-flow', 'sessions') },
475
+ { label: 'terminals', path: join(cwd, '.claude-flow', 'terminals', 'store.json') },
476
+ { label: 'memory.db', path: join(cwd, '.swarm', 'memory.db') },
477
+ ];
478
+ const status = [];
479
+ for (const s of stores) {
480
+ if (!existsSync(s.path)) {
481
+ status.push(`${s.label}=∅`);
482
+ continue;
483
+ }
484
+ try {
485
+ const stat = statSync(s.path);
486
+ if (stat.isDirectory()) {
487
+ // Sessions: probe the first .json file
488
+ const { readdirSync } = await import('fs');
489
+ const files = readdirSync(s.path).filter(f => f.endsWith('.json'));
490
+ if (files.length === 0) {
491
+ status.push(`${s.label}=∅`);
492
+ continue;
493
+ }
494
+ const first = readFileSync(join(s.path, files[0]));
495
+ status.push(`${s.label}=${isEncryptedBlob(first) ? 'enc' : 'plain'}`);
496
+ }
497
+ else {
498
+ const buf = readFileSync(s.path);
499
+ status.push(`${s.label}=${isEncryptedBlob(buf) ? 'enc' : 'plain'}`);
500
+ }
501
+ }
502
+ catch {
503
+ status.push(`${s.label}=err`);
504
+ }
505
+ }
506
+ return {
507
+ name: 'Encryption at Rest',
508
+ status: 'pass',
509
+ message: `On — key fp:${keyFingerprint}… (${status.join(' ')})`,
510
+ };
511
+ }
426
512
  // Format health check result
427
513
  function formatCheck(check) {
428
514
  const icon = check.status === 'pass' ? output.success('✓') :
@@ -494,7 +580,8 @@ export const doctorCommand = {
494
580
  checkMcpServers,
495
581
  checkDiskSpace,
496
582
  checkBuildTools,
497
- checkAgenticFlow
583
+ checkAgenticFlow,
584
+ checkEncryptionAtRest, // ADR-096 Phase 5
498
585
  ];
499
586
  const componentMap = {
500
587
  'version': checkVersionFreshness,
@@ -510,7 +597,8 @@ export const doctorCommand = {
510
597
  'mcp': checkMcpServers,
511
598
  'disk': checkDiskSpace,
512
599
  'typescript': checkBuildTools,
513
- 'agentic-flow': checkAgenticFlow
600
+ 'agentic-flow': checkAgenticFlow,
601
+ 'encryption': checkEncryptionAtRest, // ADR-096 Phase 5
514
602
  };
515
603
  let checksToRun = allChecks;
516
604
  if (component && componentMap[component]) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.6.25",
3
+ "version": "3.6.26",
4
4
  "type": "module",
5
5
  "description": "Ruflo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
6
6
  "main": "dist/src/index.js",
@@ -1 +0,0 @@
1
- {"sessionId":"36428a63-dfb2-42a4-a159-cf8be916193e","pid":71027,"procStart":"Sun May 3 23:00:23 2026","acquiredAt":1777849234814}