Releases: Perseus-Computing-LLC/perseus-vault
Release list
v2.17.4 — security housekeeping (2026-07-05)
Patch release shipping the 2026-07-05 review housekeeping (#461).
- Removed the dead
--workspace-tokenflag — it was documented as cross-workspace-access auth but no code read it (a control that looked active and wasn't). Transport auth is--mcp-token; workspace scoping is a routing control, not an enforced boundary (seedocs/THREAT-MODEL.md). Passing--workspace-tokennow errors instead of silently no-op'ing.
See docs/security-review-2026-07-05.md.
v2.17.3 — security review (2026-07-05)
Patch release carrying the 2026-07-05 pre-launch security review fixes.
Supply-chain / deploy (#457): install.sh checksum verification now fails closed (missing .sha256 or missing hash tool aborts; opt out with PERSEUS_VAULT_INSECURE_SKIP_CHECKSUM=1); Docker image runs as a non-root vault user; new Security Audit CI workflow runs cargo audit on every push/PR (making the SECURITY.md claim true).
Hardening (#458): traverse clamps caller-supplied max_depth/max_nodes; dense recall clamps a negative limit; GitHub connector validates repo as strict owner/name.
Audit-chain (#460): the journal chain is now a real SHA-256 hash chain (was a 64-bit non-cryptographic DefaultHasher); new verify-audit-chain CLI command (the verifier was previously never invoked); v13→v14 rehash migration. The chain deliberately covers event existence/order/time/workspace (not payload, so purge erasure stays compatible) and remains unkeyed — a keyed MAC for full tamper-evidence is the tracked follow-up.
Full ranked review: docs/security-review-2026-07-05.md.
v2.17.2
v2.17.2 — installable Anthropic MCP Directory bundle (self-contained …
Perseus Vault v2.17.1
[2.17.1] - 2026-07-04
Fixed
install.shwas broken for every prebuilt install. It downloaded a bare
perseus-vault-${TARGET}asset name, but releases ship.tar.gzarchives
(+.sha256), so the download 404'd on every platform and fell through to the
build-from-source path. Now downloads the.tar.gz, extracts the binary, and
verifies the published checksum (hard-fail on mismatch). Also corrected the
platform→asset map: aarch64-linux ships only thelitemusl build (the old
code requested a nonexistent-gnuasset). (#451)- MCP Registry publish (had failed on v2.16.0 and v2.17.0): the Docker
image'sio.modelcontextprotocol.server.nameOCI annotation was still
io.github.Perseus-Computing-LLC/mimirwhileserver.jsonhad moved to
…/perseus-vault, so the registry's ownership validation rejected the publish
with a 400. The label now matchesserver.json, so v2.17.1 publishes under the
perseus-vaultnamespace. (#452)
Changed
- Dropped prebuilt macOS Intel (x86_64-apple-darwin) release binaries. The
macos-13runner class is chronically backlogged and repeatedly stalled the
release pipeline for ~1h. Apple Silicon (aarch64-apple-darwin) covers modern
Macs; Intel-Mac users cancargo install --git …from source (or run the lite
musl build under Rosetta).install.shdegrades gracefully with a source-build
hint for that target. (#447)
v2.17.0
Security / Hardening
- Multimodal ingest is now bounded against decompression bombs. A
.docxis a
DEFLATE zip, so a tiny on-disk file (withinMIMIR_MAX_INGEST_BYTES) could
decompressword/document.xmlto many GB — the on-disk cap couldn't bound it,
and the read was unbounded (OOM). The decompressed read is now capped at
MIMIR_MAX_DECOMPRESSED_BYTES(default 256 MiB) and rejected past it. PDF
extraction is bounded by the on-disk cap only (pdf_extractowns decompression
with no limit API — documented; lowerMIMIR_MAX_INGEST_BYTESfor untrusted
PDFs). - Network transport & gRPC hardening (audit phases 1–3):
- Secure-bind guard: binding an HTTP surface (MCP transport or web
dashboard) to a non-loopback address with no auth token now refuses to
start instead of coming up wide open. Override with
MIMIR_ALLOW_INSECURE_BIND=1for a trusted network / auth-terminating proxy. - Constant-time token comparison for Bearer auth on both HTTP surfaces
(was a byte-wise==, a timing side-channel on the secret). - Request-body cap (
MIMIR_MAX_HTTP_BODY_BYTES, default 8 MiB) and a
global token-bucket rate limit (MIMIR_HTTP_RATE_PER_SEC/
MIMIR_HTTP_RATE_BURST, default 50 req/s + burst 100 →429). - Tightened transport CORS — explicit methods/headers instead of
Any,
with an optionalMIMIR_CORS_ALLOWED_ORIGINSallowlist. - gRPC security model:
servenow supports a Bearer-token auth interceptor
(MIMIR_GRPC_AUTH_TOKEN), TLS and mutual-TLS (MIMIR_GRPC_TLS_CERT/KEY,
MIMIR_GRPC_TLS_CLIENT_CA), a message-size cap (MIMIR_GRPC_MAX_MSG_BYTES),
and the same secure-bind guard. See docs/GRPC-SECURITY.md.
- Secure-bind guard: binding an HTTP surface (MCP transport or web
- Encryption canary (fail-fast wrong-key detection).
set_encryptionnow
verifies the configured key against a dedicated canary row at startup and
aborts loudly ("the provided key is incorrect or the database is corrupt")
instead of letting a wrong/rotated key silentlyAuthFailedon every later
read. The canary is established on first encrypted setup (or when encryption is
enabled on a legacy-plaintext DB); a canary-less store with pre-existing
encrypted data is validated by scanning for authentic ciphertext, so a wrong
key can never "bless" itself by writing a canary under it. Stored in its own
encryption_canarytable — invisible to recall/FTS/stats and caller-facing
state tools. - Build-time model fetch is now supply-chain pinned (
build.rs): the bundled
all-MiniLM-L6-v2ONNX model + tokenizer are fetched from an immutable commit
revision (was the mutablemainref) and SHA-256 verified before being
baked into the binary viainclude_bytes!. A compromised or updated upstream
repo can no longer silently change the embedded model — a mismatch fails the
build. Operator-supplied files (MIMIR_BUNDLED_MODEL_DIR, air-gapped builds)
are verified against the same hashes. - Windows key-file ACLs:
keygennow restricts the new key file to the current
user viaicacls(Windows has no0600-at-creation equivalent), warning
loudly if that fails; enabling encryption on Windows also emits a one-line
runtime reminder that key-file ACLs are operator-owned. - Bumped
anyhow1.0.102 → 1.0.103 to clear RUSTSEC-2026-0190 (unsoundness in
Error::downcast_mut()).
Performance
- Empty-query browse recall no longer degrades on large stores. The browse path
orders byretrieval_count DESC, last_accessed_unix_ms DESC, id ASC, but
idx_entities_recallcovered only the first two keys — so a large tie-group on
the leading keys (a cold or bulk-imported store with uniformlast_accessed)
forced SQLite to sort the whole group byidto satisfyLIMIT k
(O(tie-group)). The index now includes theidtie-break, making browse a pure
k-row range scan. Measured p50 at 1,000,000 rows: 29.7 ms → 0.046 ms
(~645×); FTS and point-lookup latencies were already flat and are unchanged.
Ships a v13 schema migration that rebuilds the index on existing databases.
Fixed
- De-flaked
concurrent_writer_not_starved_during_cohere: the #400 lock-hold
gate asserted exactly zero SQLITE_BUSY, which spuriously failed on loaded CI
runners when OS scheduler jitter delayed a single (correctly chunked) cohere
commit past the writer's ~250ms budget. Now asserts a low busy rate (<10%) —
the #400 regression it guards produces ~100%, jitter ~0.5%, so detection is
preserved with wide margin. No production-code change.
Perseus Vault v2.16.0 — hardening + prebuilt binaries
First release to ship prebuilt binaries (#432/#435) — no more mandatory from-source build. Assets (lite static musl + full, with SHA-256 sums) are attached by the release workflow shortly after this is published.
Security / Hardening
- Audit chain binds the workspace (#438): a journal entry can no longer be moved between workspaces without breaking
verify_audit_chain. Ships a v11→v12 migration that re-hashes existing chains (so pre-upgrade chains still verify); purge redaction preservesworkspace_hashas a hashed field. - Keyfile 0600 at creation on Unix (#434) — closes the world-readable window.
rememberinput bounds (category/key/body caps) — DoS-via-huge-key (#434).- File-watcher rejects symlinks — no escaping the watch root (#434).
Added
- Prebuilt release binaries:
perseus-vault-lite(static musl, linux x86_64/aarch64) + fullperseus-vault(linux-gnu x86_64, macOS x86_64/arm64) (#432/#435). perseus-vault doctorfreshness line — surfaces a stale vault (#434).
Changed
- Default on-disk paths →
~/.perseus-vault/(precedence-only, no data moved;~/.mimir/still works); addsPERSEUS_VAULT_DB_PATH(#437). - MCP-registry name →
io.github.Perseus-Computing-LLC/perseus-vault(#436).
Full detail in CHANGELOG.md.
v2.15.0
Deploy-surface rename completion (fresh operators get a working perseus-vault config from every client/integration snippet) + the capacity/retention/DB-resolution hardening arc. See CHANGELOG [2.15.0]. bootstrap.sh build-from-source repaired (#424/#425); empty-DB-aware default resolution (#424); retention/purge, background auto-embed, FTS selectivity, cohere lock window, web/gRPC pooling, perf-gate.
v2.14.0 — bi-temporal memory + the concurrency/capacity hardening arc
Highlights
Bi-temporal memory (schema v9, 55 tools). Facts now carry a queryable valid-time axis (SQL:2011 APPLICATION_TIME) orthogonal to transaction time: mimir_valid_at, mimir_bitemporal, valid-period filters on recall, valid-time on remember/correct/supersede. Plus GraphRAG community detection (mimir_communities / mimir_community_summary / mimir_global_recall, schema v8), mimir_dream sleep-time consolidation, and recall-first context injection.
The concurrency/capacity hardening arc (#371–#405). A systematic sweep found and fixed seven instances of one defect family — read-decide-write on the bare pooled connection, missing monotonic timestamp bumps, and nested pool draws — every fix shipped with a regression test proven failing against pre-fix code:
- Pool-exhaustion collapse (#397, #387): recall/insert/embed/link each held two pooled connections; at 2× pool oversubscription the server measured 174 req/s with 30-second stalls and failed writes, and wedged at 4×. Now one connection per request: ~4,200 req/s, zero errors on the same load. New
MIMIR_POOL_TIMEOUT_MSknob. - Temporal audit-trail integrity (#371–#381): all four
entity_historywriters now take the IMMEDIATE writer lock before precondition reads and bump timestamps monotonically — no more inverted/zero-width history windows, double snapshots, or backwardsrecorded_atunder concurrency. - Link-graph durability (#382): re-remembering a linked entity no longer erases its edges — remember unions caller links with stored links under the writer lock.
- Efficacy tracking correctness (#385, #391): concurrent
mimir_followcalls no longer lose increments, and a follow stamps exactly one resolved row instead of every workspace's row of that key. - Maintenance safety (#388, #399, #400): cohere's transaction is drop-safe (an error can no longer permanently poison a pool slot); decay_tick skips no-op writes (was 412MB of WAL per tick on a 45MB DB at 100k entities).
mimir_historypagination (#403):limit(default 20) +offset+total— no more multi-MB tool responses from hot keys.- New concurrency CI gate: the pool load test at 2× oversubscription plus four concurrency hammer tests now run on every PR.
Also since v2.13.0: rekey-aad guarded against concurrent rewrites (#386), grpc build lane + error sanitization (#359), migration race fixes (#357/#358), RUSTSEC-2026-0187 cleared (#362).
Full details in the CHANGELOG.
🤖 Generated with Claude Code
Perseus Vault v2.13.0 — workspace isolation, retention semantics, /memories, dense prefilter
The largest release since the Perseus Vault rename — 24 PRs spanning v2.9.0→v2.13.0, with three schema migrations (v4→v6), full multi-workspace isolation, a coherent retention policy, and two new integration surfaces.
Security & isolation
- Workspace isolation, end to end.
context/recall_when/prepare/gRPC now accept a workspace scope (#338); entity identity is(category, key, workspace_hash)with a migrated unique index, soshare/federatecopy instead of destructively moving the source row (#342); near-duplicate detection no longer swallows one workspace's writes into another's (#338); dashboard endpoints workspace-scoped (#346). - Prompt-injection hardening: untrusted entity bodies are neutralized before splicing into
<memory-prep>/context blocks (#337); AAD delimiter collision fixed withrekey_aadmigration (#329).
Retention & memory semantics
- Documented forgetting policy — new docs/retention.md: the decay curve, the ~21-day auto-archive point, and every exemption.
- Unified constants (#337): one archive threshold across
decay_tick/cohere/autocohere; promotion atWORKING_THRESHOLDeverywhere; verified facts floored, never auto-archived. - Persistent importance (#344): an explicit
mimir_scorenow survives every decay recompute as a floor — fidelity beats recency. - Opt-in reinforcement (#343):
reinforce: trueon dense/hybrid recall makes used memories resist decay; the default stays byte-deterministic. - Local dreaming (#350):
autocoherenow consolidates the coldest overlapping memories into evidence-tracked observations and retires the merged sources (verified/importance-floored sources exempt) — compression instead of loss, running in the background. - Follow-rate efficacy scoring (#332): memories that get followed, not just recalled, resist decay; ignored rules fade.
New surfaces
mimir_memories(#345): Anthropic memory-tool directory convention (view/create/str_replace/insert/delete/renameunder/memories) — clients built against Claude's native memory tool work against the vault unchanged, with FTS search, encryption at rest, and versioned edits for free. 49 tools total.perseus-vault prepare(#336): pre-turn auto-injection — one CLI call returns the<memory-prep>block for a hook to splice into the system prompt, now workspace-scopable with--workspace.perseus-vault connect(#333): one-command MCP client setup (Claude Code, Codex, Cursor, VS Code, Hermes).
Performance
- Dense search signature prefilter (#347): sign-bit signatures (schema v6) Hamming-prefilter candidates above 2048 embedded rows — ~30× less scan I/O, exact-cosine re-rank, zero new dependencies, byte-identical below the cutover.
- Graph arm batched (#340):
graph_expand's N+1 point-queries → chunked batch hydration;consolidate's O(n²) trigram rebuilds → cached sets. - Hybrid recall gains a graph-expansion arm (#326): entities linked to a strong hit surface even when they rank poorly on keywords or embeddings alone.
Fixes worth knowing about
- Revived entities (forget → remember) were silently unsearchable forever — FTS row now restored (#345).
mimir_remember/mimir_recallaccept explicit JSONnullon optional fields (#334).as_ofzero-width history window, staleserverInfo.name, DOCX self-closing-tag corruption, and a build-break from two textually-clean-but-semantically-conflicting merges (#331, #324, #349).
Migrations: schema v3→v6 apply automatically and irreversibly on first open (unique-index swap, importance, emb_sig + signature backfill). Back up the DB file before upgrading if you may need to roll back the binary.
🤖 Generated with Claude Code
Mneme v2.8.0 — renamed from Mimir
Mimir is now Mneme — same memory engine, same team, new name. The rename avoids a trademark/SEO collision with Grafana Mimir and a same-niche competitor also named Mimir.
Upgrading: fully backward compatible for one transition release.
- Every
mimir_*MCP tool is also registered asmneme_*— both work. - An existing
~/.mimir/data/mimir.dbis still used automatically ifmneme.dbdoesn't exist yet — no data migration needed. - The Docker image keeps a
mimirsymlink alongside the newmnemebinary.
Image: ghcr.io/perseus-computing-llc/mneme:2.8.0
See CHANGELOG.md for the full list of changes in this release.