DEV Community

RagLeap
RagLeap

Posted on

I Built Tenant-Scoped Memory That Erases for Real — 89 Tests, 27 Mutations, Byte-Level Verified

ragleap-memory 0.1.0 + ragleap-security 0.1.0 — One SQLite File, Real Erasure, Scope Enforced in SQL

I just released two new libraries: ragleap-security 0.1.0 (101 tests) and ragleap-memory 0.1.0 (89 tests). Both v0.1.0, both first releases, both with mutation testing.

TL;DR: Tenant isolation enforced inside SQL, not in app code. And erase() actually removes bytes.

ragleap-security — stdlib only

from ragleap_security import Scope, AuditLog, SecretStr, check_size

scope = Scope.parse("org:gov-dept/region:south/branch:chennai")
print(scope.covers(Scope.parse("org:gov-dept/region:south"))) # True

child = scope.narrow("facility:factory1")

org:gov-dept/region:south/branch:chennai/facility:factory1

log = AuditLog("audit.jsonl")
log.append({"op": "add", "scope": str(scope)})
log.verify() # hash-chain check

secret = SecretStr("sk-...")
print(secret) # SecretStr(***) — never leaks in repr
check_size(data, max_bytes=1_000_000)

5 modules, no deps. You can audit it in an afternoon.

Why hash-chained JSONL? Tamper-evident. If someone edits line 10, verify() fails because hash chain breaks. Not tamper-proof (can't prevent edit), but can detect.

Verified: 101 tests, 30/30 mutations killed, reproducible build matches PyPI.

ragleap-memory — the interesting part

Problem with most memory libs: They do SELECT * FROM memories WHERE tenant_id = X in app code. But they still return different errors for "not found" vs "not allowed" — leaking existence.

Our approach: scope filtering inside SQL, same response for missing vs outside-scope.

from ragleap_memory import SQLiteStore
from ragleap_security import Scope

store = SQLiteStore("memory.db")
scope_a = Scope.parse("org:hospital/branch:chennai")
scope_b = Scope.parse("org:hospital/branch:mumbai")

store.add(text="ICU bed count changed to 12", type="fact", trust="trusted", scope=scope_a)

Same scope → found

print(store.search("ICU", scope=scope_a)) # [fact]

Different scope → looks like missing, not "access denied"

print(store.search("ICU", scope=scope_b)) # [] — same as missing

Typed entries: episode (raw events), fact (distilled), summary (compressed). All default to untrusted — you must explicitly trust.

Operations that matter for enterprise:

id1 = store.add(text="Old threshold", type="fact", scope=scope_a)
id2 = store.supersede(id1, text="New threshold is 80", scope=scope_a) # history kept

store.forget(id2, scope=scope_a) # soft delete
store.erase(id2, scope=scope_a) # hard delete + vacuum

After erase, byte-level check:

grep -a "New threshold" memory.db → not found

grep -a "New threshold" memory.db-journal → not found

We actually tested byte-level search after erase on two SQLite builds.

Other ops: export (dump for migration), sweep_expired (TTL), compact (vacuum), optional audit log without entry text (privacy).

FTS5 search: Full-text search, not vector. Why? Deterministic, no embedding cost, works offline. For Hindi, Tamil, Arabic, Chinese with spaces — whole-word tested. Without spaces (Chinese/Japanese) — not split yet, known limit.

Mutation testing

We run scripts/mutation_check.py — it mutates code (change == to !=, remove WHERE clause, etc.) and checks tests kill it.

security: 30/30 killed

memory: 27/27 killed

If a mutation survives, your tests are weak. We fixed until all killed.

Reproducible builds

Build locally before tagging, compute SHA-256, build on CI after tagging, compare. If different, fail. For these releases, local SHA matches PyPI SHA.

ragleap_memory-0.1.0-py3-none-any.whl sha256 c60a1e4f91e323c04ba04d7628abb7028039206d2330921a7ca00ae053a3533e
ragleap_security-0.1.0-py3-none-any.whl sha256 e3f31d3703d552cde53080e6d6c56cef733954d61deeaba586bdce48db53075d

Not verified — honest

No Windows / NFS / multi-process writes / power-loss tests
No retrieval benchmark (precision/recall unmeasured)
Tenant isolation holds inside lib, but nothing else uses it yet
No independent security review — see docs/threat-model.md

Install

pip install ragleap-security==0.1.0
pip install ragleap-memory==0.1.0

Repo: github.com/ragleap/ragleap-core

Release PRs: #907 (security), #922/#924 (memory)
Workflows: 40016023080, 40060689857

This is foundation for human digital twins and org-wide memory with real isolation. Next: integrate Scope into agents.

If you care about multi-tenant AI, try breaking the scope isolation — I'd love a failing test.

Top comments (0)