Context
Neo has several legitimate destructive operations for AI substrate maintenance: dropping Chroma collections, truncating Memory Core graph tables, and replacing imported graph state. Those operations are useful when an operator intentionally resets a disposable test store or runs a controlled substrate maintenance task.
The preventive hardening gap is that destructive call sites currently rely on caller discipline to ensure the active target is disposable. Tests and maintenance scripts should have a shared failsafe that refuses destructive operations unless the resolved storage target is clearly test-local, temporary, or explicitly operator-authorized.
This ticket is preventive operational substrate / MX hardening. It creates a reusable path-discipline primitive for destructive AI-store operations across Memory Core and Knowledge Base surfaces.
The Problem
Test isolation tickets and local tmp-path conventions reduce accidental pollution, but they do not form a universal guard around the destructive operations themselves. If a test, script, or MCP call reaches a destructive method with production-like defaults still active, the destructive method has no final path-aware stop sign.
The dangerous operation classes are narrow and identifiable:
- Chroma collection deletion, such as Memory Core
CollectionProxy.drop().
- Knowledge Base collection deletion through
VectorService.deleteCollection().
- SQLite graph table truncation or replace-mode import.
- Any future mass-delete or drop path added to Memory Core / Knowledge Base services.
The fix belongs at the destructive boundary, not only in individual specs. Every destructive call should prove the target is disposable before it executes.
The Architectural Reality
ai/mcp/server/memory-core/managers/CollectionProxy.mjs:87-105 drops Memory Core Chroma collections through deleteCollection.
ai/mcp/server/memory-core/services/DatabaseService.mjs:229-233 truncates graph tables during replace-mode graph import.
ai/mcp/server/memory-core/services/DatabaseService.mjs:456-504 exposes truncateDatabase() for memories, summaries, and graph.
ai/mcp/server/knowledge-base/services/VectorService.mjs:55-63 deletes the Knowledge Base Chroma collection.
ai/mcp/server/knowledge-base/services/DatabaseService.mjs:249-260 exposes the delete action through manageKnowledgeBase().
ai/mcp/server/memory-core/config.mjs:197-199 defines the default Memory Core graph path under .neo-ai-data/sqlite/.
ai/mcp/server/knowledge-base/config.mjs:114 defines the default Knowledge Base Chroma path under .neo-ai-data/chroma/knowledge-base.
- Prior test-isolation work (#9746, #10786) shows that local test path discipline is a recurring substrate concern, but this ticket is a lower-level failsafe around destructive operations themselves.
The Fix
Introduce a shared destructive-operation guard for AI data stores.
The guard should resolve the active target path or storage descriptor before destructive execution and allow the operation only when one of these is true:
- The target is explicitly in-memory (
:memory:).
- The resolved target is under a disposable test root, such as
os.tmpdir() or repo-local tmp/.
- A legitimate production destructive operation is explicitly authorized by both
process.env.NEO_ALLOW_PRODUCTION_DESTRUCTIVE === 'true' and an operator-confirmation mechanism appropriate to the caller surface.
Use the guard at Memory Core and Knowledge Base destructive call sites. Avoid one-off regex checks scattered through specs; the point is a reusable substrate primitive.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback / Edge Case |
Docs |
Evidence |
| Destructive AI-store guard helper |
This ticket, prior test-isolation substrate work |
Accepts operation metadata and a resolved target descriptor; returns success only for disposable targets or explicitly authorized production operations. |
Missing, relative, or unresolved paths fail closed with an operator-actionable error. |
JSDoc documents accepted disposable targets and bypass contract. |
Unit tests for :memory:, temp paths, repo tmp/, production defaults, and missing paths. |
| Memory Core Chroma drop path |
CollectionProxy.drop() |
Calls the guard before deleting memory/session Chroma collections. |
Refuses deletion when the active target cannot be proven disposable and no operator bypass is present. |
Method docs name the guard and bypass contract. |
Targeted test proves production-like collection drop is blocked and tmp-backed drop succeeds. |
| Memory Core SQLite graph truncation |
DatabaseService.truncateDatabase() and replace-mode graph import |
Calls the guard before DELETE FROM Nodes / DELETE FROM Edges or equivalent mass-delete paths. |
Refuses truncation for default .neo-ai-data/sqlite/ paths unless operator bypass is present. |
DatabaseService docs updated. |
Targeted tests for graph truncate allowed under tmp and blocked under production-like path. |
| Knowledge Base collection deletion |
VectorService.deleteCollection() / manageKnowledgeBase({action: 'delete'}) |
Calls the guard before deleting the KB Chroma collection. |
Refuses deletion for default .neo-ai-data/chroma/knowledge-base unless operator bypass is present. |
KB deletion docs updated. |
Targeted tests for KB delete allowed under tmp and blocked under production-like path. |
| Production destructive bypass |
Operator confirmation contract |
Requires NEO_ALLOW_PRODUCTION_DESTRUCTIVE=true plus an explicit confirmation mechanism. |
Env var alone is insufficient if the caller surface can provide a confirmation prompt/token; noninteractive surfaces must return a clear blocked error unless explicitly designed otherwise. |
Operator docs state the exact bypass flow. |
Tests prove env-only bypass fails where confirmation is required. |
Acceptance Criteria
Out of Scope
- Changing normal read/write Memory Core or Knowledge Base behavior.
- Removing legitimate maintenance operations.
- Reworking all test path setup. This ticket guards destructive boundaries; individual test cleanup remains separate.
- Reactive postmortem framing. This is preventive substrate hardening.
Avoided Traps
- Spec-only patching: fixing individual tests does not protect future scripts or MCP paths.
- String-only regex discipline: the guard should resolve paths where possible before deciding whether a target is disposable.
- Env-only bypass: a single environment flag is too easy to inherit accidentally; production destructive behavior needs an operator confirmation step.
Related
- #9746 — local test data isolation under workspace tmp
- #10786 — test-isolation bug in harness lifecycle tests
- #10822 — config substrate cleanup epic context
Origin Session ID: ab6b2fad-6660-4148-a0c7-474c0131a6bf
Retrieval Hint: query_raw_memories(query="destructive operation production path guard deleteCollection SQLite truncate test isolation")
Context
Neo has several legitimate destructive operations for AI substrate maintenance: dropping Chroma collections, truncating Memory Core graph tables, and replacing imported graph state. Those operations are useful when an operator intentionally resets a disposable test store or runs a controlled substrate maintenance task.
The preventive hardening gap is that destructive call sites currently rely on caller discipline to ensure the active target is disposable. Tests and maintenance scripts should have a shared failsafe that refuses destructive operations unless the resolved storage target is clearly test-local, temporary, or explicitly operator-authorized.
This ticket is preventive operational substrate / MX hardening. It creates a reusable path-discipline primitive for destructive AI-store operations across Memory Core and Knowledge Base surfaces.
The Problem
Test isolation tickets and local tmp-path conventions reduce accidental pollution, but they do not form a universal guard around the destructive operations themselves. If a test, script, or MCP call reaches a destructive method with production-like defaults still active, the destructive method has no final path-aware stop sign.
The dangerous operation classes are narrow and identifiable:
CollectionProxy.drop().VectorService.deleteCollection().The fix belongs at the destructive boundary, not only in individual specs. Every destructive call should prove the target is disposable before it executes.
The Architectural Reality
ai/mcp/server/memory-core/managers/CollectionProxy.mjs:87-105drops Memory Core Chroma collections throughdeleteCollection.ai/mcp/server/memory-core/services/DatabaseService.mjs:229-233truncates graph tables during replace-mode graph import.ai/mcp/server/memory-core/services/DatabaseService.mjs:456-504exposestruncateDatabase()for memories, summaries, and graph.ai/mcp/server/knowledge-base/services/VectorService.mjs:55-63deletes the Knowledge Base Chroma collection.ai/mcp/server/knowledge-base/services/DatabaseService.mjs:249-260exposes thedeleteaction throughmanageKnowledgeBase().ai/mcp/server/memory-core/config.mjs:197-199defines the default Memory Core graph path under.neo-ai-data/sqlite/.ai/mcp/server/knowledge-base/config.mjs:114defines the default Knowledge Base Chroma path under.neo-ai-data/chroma/knowledge-base.The Fix
Introduce a shared destructive-operation guard for AI data stores.
The guard should resolve the active target path or storage descriptor before destructive execution and allow the operation only when one of these is true:
:memory:).os.tmpdir()or repo-localtmp/.process.env.NEO_ALLOW_PRODUCTION_DESTRUCTIVE === 'true'and an operator-confirmation mechanism appropriate to the caller surface.Use the guard at Memory Core and Knowledge Base destructive call sites. Avoid one-off regex checks scattered through specs; the point is a reusable substrate primitive.
Contract Ledger Matrix
:memory:, temp paths, repotmp/, production defaults, and missing paths.CollectionProxy.drop()DatabaseService.truncateDatabase()and replace-mode graph importDELETE FROM Nodes/DELETE FROM Edgesor equivalent mass-delete paths..neo-ai-data/sqlite/paths unless operator bypass is present.VectorService.deleteCollection()/manageKnowledgeBase({action: 'delete'}).neo-ai-data/chroma/knowledge-baseunless operator bypass is present.NEO_ALLOW_PRODUCTION_DESTRUCTIVE=trueplus an explicit confirmation mechanism.Acceptance Criteria
:memory:targets and resolved disposable test roots..neo-ai-data/Memory Core / Knowledge Base targets by default.deleteCollection.deleteCollection.NEO_ALLOW_PRODUCTION_DESTRUCTIVE=trueplus explicit operator confirmation.Out of Scope
Avoided Traps
Related
Origin Session ID: ab6b2fad-6660-4148-a0c7-474c0131a6bf
Retrieval Hint:
query_raw_memories(query="destructive operation production path guard deleteCollection SQLite truncate test isolation")