claude-flow 3.59.7 → 3.59.9
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/.claude/proven-config.json +1 -1
- package/node_modules/@claude-flow/codex/package.json +0 -1
- package/package.json +1 -2
- package/v3/@claude-flow/cli/catalog-manifest.json +2 -2
- package/v3/@claude-flow/cli/dist/src/mcp-tools/config-tools.js +4 -2
- package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +25 -2
- package/v3/@claude-flow/cli/dist/src/memory/memory-initializer.js +15 -2
- package/v3/@claude-flow/cli/package.json +1 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow",
|
|
3
|
-
"version": "3.59.
|
|
3
|
+
"version": "3.59.9",
|
|
4
4
|
"workspaces": [
|
|
5
5
|
"v3/@claude-flow/codex",
|
|
6
6
|
"v3/@claude-flow/mcp",
|
|
@@ -91,7 +91,6 @@
|
|
|
91
91
|
"helmet": "^7.2.0",
|
|
92
92
|
"inquirer": "^9.2.0",
|
|
93
93
|
"semver": "7.7.3",
|
|
94
|
-
"toml": "^3.0.0",
|
|
95
94
|
"ws": ">=8.21.0",
|
|
96
95
|
"yaml": "^2.8.0",
|
|
97
96
|
"zod": "3.25.76"
|
|
@@ -339,10 +339,12 @@ export const configTools = [
|
|
|
339
339
|
merged.set(key, { value, source: 'stored' });
|
|
340
340
|
}
|
|
341
341
|
// Always include keys from every scope so they're discoverable; the
|
|
342
|
-
// scope filter only narrows which set is used as the *winner*.
|
|
342
|
+
// scope filter only narrows which set is used as the *winner*. The
|
|
343
|
+
// default scope has no scope of its own, so stored values win there,
|
|
344
|
+
// as in config_get and config_export.
|
|
343
345
|
for (const [scopeName, scopeValues] of Object.entries(store.scopes)) {
|
|
344
346
|
for (const [key, value] of Object.entries(scopeValues)) {
|
|
345
|
-
if (scope === scopeName
|
|
347
|
+
if (scope === scopeName) {
|
|
346
348
|
merged.set(key, { value, source: `scope:${scopeName}` });
|
|
347
349
|
}
|
|
348
350
|
else if (!merged.has(key)) {
|
|
@@ -1659,12 +1659,29 @@ export async function bridgeDeleteEntry(options) {
|
|
|
1659
1659
|
if (!guardResult.allowed) {
|
|
1660
1660
|
return { success: false, deleted: false, key, namespace, remainingEntries: 0, error: `MutationGuard rejected: ${guardResult.reason}` };
|
|
1661
1661
|
}
|
|
1662
|
-
//
|
|
1662
|
+
// #3785: secure_delete zeroes the old cells while the payload columns are
|
|
1663
|
+
// scrubbed; otherwise SQLite can leave the deleted text in free pages.
|
|
1664
|
+
try {
|
|
1665
|
+
ctx.db.pragma('secure_delete = ON');
|
|
1666
|
+
}
|
|
1667
|
+
catch { /* non-fatal: the logical scrub below still hides the row */ }
|
|
1668
|
+
// Soft delete using parameterized query. The tombstone must keep only
|
|
1669
|
+
// what later upserts/audits need: the payload columns are scrubbed here,
|
|
1670
|
+
// not merely hidden by the status filter. `content` is NOT NULL in the
|
|
1671
|
+
// schema, so "scrubbed" is the empty string rather than SQL NULL; that
|
|
1672
|
+
// still removes the deleted value from disk and from any raw SQLite read.
|
|
1663
1673
|
let changes = 0;
|
|
1664
1674
|
try {
|
|
1665
1675
|
const result = ctx.db.prepare(`
|
|
1666
1676
|
UPDATE memory_entries
|
|
1667
|
-
SET status = 'deleted',
|
|
1677
|
+
SET status = 'deleted',
|
|
1678
|
+
content = '',
|
|
1679
|
+
embedding = NULL,
|
|
1680
|
+
embedding_model = NULL,
|
|
1681
|
+
embedding_dimensions = NULL,
|
|
1682
|
+
tags = NULL,
|
|
1683
|
+
metadata = NULL,
|
|
1684
|
+
updated_at = ?
|
|
1668
1685
|
WHERE key = ? AND namespace = ? AND ${ACTIVE_MEMORY_ROW_SQL}
|
|
1669
1686
|
`).run(Date.now(), key, namespace);
|
|
1670
1687
|
changes = result?.changes ?? 0;
|
|
@@ -1737,6 +1754,12 @@ export async function bridgePurgeNamespace(options) {
|
|
|
1737
1754
|
}
|
|
1738
1755
|
let deletedCount = 0;
|
|
1739
1756
|
try {
|
|
1757
|
+
// #3785: a hard DELETE without secure_delete leaves the purged payload
|
|
1758
|
+
// in free pages; purge claims to be irreversible.
|
|
1759
|
+
try {
|
|
1760
|
+
ctx.db.pragma('secure_delete = ON');
|
|
1761
|
+
}
|
|
1762
|
+
catch { /* non-fatal: the rows are still removed below */ }
|
|
1740
1763
|
const result = ctx.db.prepare(`DELETE FROM memory_entries WHERE namespace = ?`).run(namespace);
|
|
1741
1764
|
deletedCount = result?.changes ?? 0;
|
|
1742
1765
|
}
|
|
@@ -3338,6 +3338,10 @@ export async function deleteEntry(options) {
|
|
|
3338
3338
|
const SQL = await initSqlJs();
|
|
3339
3339
|
const fileBuffer = readFileMaybeEncrypted(dbPath, null);
|
|
3340
3340
|
const db = new SQL.Database(fileBuffer);
|
|
3341
|
+
// #3785: zero the old cells as well as the live row. Without
|
|
3342
|
+
// secure_delete, UPDATE leaves the previous text in SQLite free pages,
|
|
3343
|
+
// so the "deleted" value is still recoverable from the file image.
|
|
3344
|
+
db.run('PRAGMA secure_delete = ON');
|
|
3341
3345
|
// Check if entry exists first
|
|
3342
3346
|
const checkStmt = db.prepare(`
|
|
3343
3347
|
SELECT id FROM memory_entries
|
|
@@ -3367,12 +3371,19 @@ export async function deleteEntry(options) {
|
|
|
3367
3371
|
error: `Key '${key}' not found in namespace '${namespace}'`
|
|
3368
3372
|
};
|
|
3369
3373
|
}
|
|
3370
|
-
//
|
|
3371
|
-
//
|
|
3374
|
+
// Soft delete by setting status to 'deleted'. Scrub the payload, not
|
|
3375
|
+
// only the vector: a tombstone that keeps `content` on disk still
|
|
3376
|
+
// exposes deleted data to anyone who opens the SQLite file. `content`
|
|
3377
|
+
// is NOT NULL, so use the empty string rather than SQL NULL.
|
|
3372
3378
|
db.run(`
|
|
3373
3379
|
UPDATE memory_entries
|
|
3374
3380
|
SET status = 'deleted',
|
|
3381
|
+
content = '',
|
|
3375
3382
|
embedding = NULL,
|
|
3383
|
+
embedding_model = NULL,
|
|
3384
|
+
embedding_dimensions = NULL,
|
|
3385
|
+
tags = NULL,
|
|
3386
|
+
metadata = NULL,
|
|
3376
3387
|
updated_at = strftime('%s', 'now') * 1000
|
|
3377
3388
|
WHERE key = ?
|
|
3378
3389
|
AND namespace = ?
|
|
@@ -3547,6 +3558,8 @@ export async function purgeNamespace(options) {
|
|
|
3547
3558
|
const SQL = await initSqlJs();
|
|
3548
3559
|
const fileBuffer = readFileMaybeEncrypted(dbPath, null);
|
|
3549
3560
|
const db = new SQL.Database(fileBuffer);
|
|
3561
|
+
// #3785: purge is advertised as irreversible; zero free pages too.
|
|
3562
|
+
db.run('PRAGMA secure_delete = ON');
|
|
3550
3563
|
const beforeResult = db.exec(`SELECT COUNT(*) FROM memory_entries WHERE namespace = ?`, [namespace]);
|
|
3551
3564
|
const deletedCount = beforeResult[0]?.values?.[0]?.[0] || 0;
|
|
3552
3565
|
db.run(`DELETE FROM memory_entries WHERE namespace = ?`, [namespace]);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.59.
|
|
3
|
+
"version": "3.59.9",
|
|
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",
|
|
@@ -123,7 +123,6 @@
|
|
|
123
123
|
"inquirer": "^9.2.0",
|
|
124
124
|
"semver": "7.7.3",
|
|
125
125
|
"sql.js": "^1.13.0",
|
|
126
|
-
"toml": "^3.0.0",
|
|
127
126
|
"ws": "^8.21.0",
|
|
128
127
|
"yaml": "^2.8.0",
|
|
129
128
|
"zod": "^3.22.0",
|