Skip to content

Releases: Perseus-Computing-LLC/perseus-vault

v2.17.4 — security housekeeping (2026-07-05)

Choose a tag to compare

@tcconnally tcconnally released this 05 Jul 23:47
985eec7

Patch release shipping the 2026-07-05 review housekeeping (#461).

  • Removed the dead --workspace-token flag — 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 (see docs/THREAT-MODEL.md). Passing --workspace-token now errors instead of silently no-op'ing.

See docs/security-review-2026-07-05.md.

v2.17.3 — security review (2026-07-05)

Choose a tag to compare

@tcconnally tcconnally released this 05 Jul 22:54
1862709

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

Choose a tag to compare

@github-actions github-actions released this 05 Jul 19:03
4856157
v2.17.2 — installable Anthropic MCP Directory bundle (self-contained …

Perseus Vault v2.17.1

Choose a tag to compare

@tcconnally tcconnally released this 04 Jul 18:23
24da42e

[2.17.1] - 2026-07-04

Fixed

  • install.sh was broken for every prebuilt install. It downloaded a bare
    perseus-vault-${TARGET} asset name, but releases ship .tar.gz archives
    (+ .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 the lite musl build (the old
    code requested a nonexistent -gnu asset). (#451)
  • MCP Registry publish (had failed on v2.16.0 and v2.17.0): the Docker
    image's io.modelcontextprotocol.server.name OCI annotation was still
    io.github.Perseus-Computing-LLC/mimir while server.json had moved to
    …/perseus-vault, so the registry's ownership validation rejected the publish
    with a 400. The label now matches server.json, so v2.17.1 publishes under the
    perseus-vault namespace. (#452)

Changed

  • Dropped prebuilt macOS Intel (x86_64-apple-darwin) release binaries. The
    macos-13 runner class is chronically backlogged and repeatedly stalled the
    release pipeline for ~1h. Apple Silicon (aarch64-apple-darwin) covers modern
    Macs; Intel-Mac users can cargo install --git … from source (or run the lite
    musl build under Rosetta). install.sh degrades gracefully with a source-build
    hint for that target. (#447)

v2.17.0

Choose a tag to compare

@tcconnally tcconnally released this 04 Jul 13:59
9e472e6

Security / Hardening

  • Multimodal ingest is now bounded against decompression bombs. A .docx is a
    DEFLATE zip, so a tiny on-disk file (within MIMIR_MAX_INGEST_BYTES) could
    decompress word/document.xml to 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_extract owns decompression
    with no limit API — documented; lower MIMIR_MAX_INGEST_BYTES for 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=1 for 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 optional MIMIR_CORS_ALLOWED_ORIGINS allowlist.
    • gRPC security model: serve now 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.
  • Encryption canary (fail-fast wrong-key detection). set_encryption now
    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 silently AuthFailed on 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_canary table — 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-v2 ONNX model + tokenizer are fetched from an immutable commit
    revision
    (was the mutable main ref) and SHA-256 verified before being
    baked into the binary via include_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: keygen now restricts the new key file to the current
    user via icacls (Windows has no 0600-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 anyhow 1.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 by retrieval_count DESC, last_accessed_unix_ms DESC, id ASC, but
    idx_entities_recall covered only the first two keys — so a large tie-group on
    the leading keys (a cold or bulk-imported store with uniform last_accessed)
    forced SQLite to sort the whole group by id to satisfy LIMIT k
    (O(tie-group)). The index now includes the id tie-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

Choose a tag to compare

@tcconnally tcconnally released this 03 Jul 23:30
597a899

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 preserves workspace_hash as a hashed field.
  • Keyfile 0600 at creation on Unix (#434) — closes the world-readable window.
  • remember input 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) + full perseus-vault (linux-gnu x86_64, macOS x86_64/arm64) (#432/#435).
  • perseus-vault doctor freshness line — surfaces a stale vault (#434).

Changed

  • Default on-disk paths → ~/.perseus-vault/ (precedence-only, no data moved; ~/.mimir/ still works); adds PERSEUS_VAULT_DB_PATH (#437).
  • MCP-registry name → io.github.Perseus-Computing-LLC/perseus-vault (#436).

Full detail in CHANGELOG.md.

v2.15.0

Choose a tag to compare

@tcconnally tcconnally released this 03 Jul 15:04
6de3e11

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

Choose a tag to compare

@tcconnally tcconnally released this 02 Jul 17:08
a56e9fd

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_MS knob.
  • Temporal audit-trail integrity (#371#381): all four entity_history writers now take the IMMEDIATE writer lock before precondition reads and bump timestamps monotonically — no more inverted/zero-width history windows, double snapshots, or backwards recorded_at under 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_follow calls 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_history pagination (#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

Choose a tag to compare

@tcconnally tcconnally released this 02 Jul 02:07
a3ddb46

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, so share/federate copy 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 with rekey_aad migration (#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 at WORKING_THRESHOLD everywhere; verified facts floored, never auto-archived.
  • Persistent importance (#344): an explicit mimir_score now survives every decay recompute as a floor — fidelity beats recency.
  • Opt-in reinforcement (#343): reinforce: true on dense/hybrid recall makes used memories resist decay; the default stays byte-deterministic.
  • Local dreaming (#350): autocohere now 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/rename under /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_recall accept explicit JSON null on optional fields (#334).
  • as_of zero-width history window, stale serverInfo.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

Choose a tag to compare

@tcconnally tcconnally released this 30 Jun 23:27
59d5657

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 as mneme_* — both work.
  • An existing ~/.mimir/data/mimir.db is still used automatically if mneme.db doesn't exist yet — no data migration needed.
  • The Docker image keeps a mimir symlink alongside the new mneme binary.

Image: ghcr.io/perseus-computing-llc/mneme:2.8.0

See CHANGELOG.md for the full list of changes in this release.