Skip to content

Releases: quantumpipes/vault

v1.6.0

10 Apr 15:41

Choose a tag to compare

Knowledge Graph

Embeds a full knowledge graph into qp-vault as the qp_vault.graph subpackage. Access via vault.graph on any AsyncVault or Vault instance. Works on both PostgreSQL and SQLite with zero additional dependencies.

Highlights

  • GraphEngine: Typed async CRUD for nodes, edges, mentions, traversal, merge, and scan. Every mutation fires a VaultEvent for capsule audit.
  • Dual-backend storage: PostgreSQL (pg_trgm similarity search, recursive CTE traversal) and SQLite (FTS5 search, Python BFS traversal).
  • Intelligence services: KnowledgeExtractor (LLM-based extraction), EntityResolver (three-stage dedup), EntityDetector (in-memory matching), EntityMaterializer (profile.md + manifest.json), WikilinkResolver.
  • Graph-augmented search: vault.search(query, graph_boost=True) detects entities in queries and boosts matching documents.
  • Membrane sanitization: NFKC normalization, HTML escaping, XML wrapping for LLM extraction input.
  • 10 graph EventTypes for capsule audit: ENTITY_CREATE, ENTITY_UPDATE, ENTITY_DELETE, EDGE_CREATE, EDGE_DELETE, ENTITY_MERGE, MENTION_TRACK, SCAN_START, SCAN_COMPLETE, SCAN_FAIL.

Quick start

from qp_vault import AsyncVault

vault = AsyncVault("./my-knowledge")
await vault._ensure_initialized()

alice = await vault.graph.create_node(name="Alice", entity_type="person")
acme = await vault.graph.create_node(name="Acme Corp", entity_type="company")
await vault.graph.create_edge(source_id=alice.id, target_id=acme.id, relation_type="works_at")

results = await vault.graph.search_nodes("Alice")
neighbors = await vault.graph.neighbors(alice.id, depth=2)

Security

100/100 security audit score. Input validation at every boundary: name/type/relation length caps, properties size cap (50KB), tag limits, weight bounds, null byte stripping, self-edge/self-merge rejection, SQL identifier validation on graph_schema, parameterized queries everywhere.

Testing

213 new graph tests (1048 total). Zero regressions.

Install

pip install qp-vault              # Graph included, no extra deps
pip install qp-vault[postgres]    # + PostgreSQL backend
pip install qp-vault[all]         # Everything

Full changelog

See CHANGELOG.md for the complete list of changes.

v1.5.2

09 Apr 02:13

Choose a tag to compare

Fix: PostgresBackend SSL default changed to prefer

Problem: PostgresBackend defaulted to ssl=True, which forced SSL negotiation. PostgreSQL servers without TLS certificates (Docker, local dev, private cloud networks) rejected the connection:

PostgreSQL server at "postgres:5432" rejected SSL upgrade

Fix: Default SSL mode changed to "prefer" (try SSL first, fall back to plaintext). This matches the standard libpq default behavior that PostgreSQL users expect.

Migration: No code changes required. Existing ssl=True is normalized to "prefer" (same behavior in SSL-capable environments, now also works without SSL). Explicit sslmode= in DSN always takes precedence.

New SSL modes

# Default: try SSL, fall back to plaintext
PostgresBackend("postgresql://localhost/db")                    # ssl="prefer"

# Force SSL (production with TLS-enabled PostgreSQL)
PostgresBackend("postgresql://localhost/db", ssl="require")

# Disable SSL explicitly
PostgresBackend("postgresql://localhost/db", ssl="disable")

# DSN always wins
PostgresBackend("postgresql://localhost/db?sslmode=require")    # require regardless of ssl= param

Full changelog: v1.5.1...v1.5.2

v1.5.1 - Security Patch: Adversarial Persistence

09 Apr 00:01

Choose a tag to compare

Security Patch: Adversarial Status Persistence

Fixes the last remaining gap from the Wizard security audit. Adversarial verification status now survives process restarts.

What Changed

  • Adversarial status persistence (FIX-4): AdversarialVerifier.get_status() now falls back to the storage backend when the in-memory cache misses. Previously, all resources reverted to UNVERIFIED on restart, losing human-reviewed VERIFIED and SUSPICIOUS classifications.

What Was Already Fixed

The other 6 items from the Wizard security gap analysis were resolved in prior releases:

Fix Status Release
FIX-1: Quarantine blocks direct retrieval Already fixed v1.3.0+
FIX-2: Classification enforcement on cloud embedders Already fixed v1.3.0+
FIX-3: Freshness decay activation Already fixed v1.3.0+
FIX-4: Adversarial status persistence Fixed this release v1.5.1
FIX-5: PostgreSQL SSL enforcement Already fixed v1.3.0+
FIX-6: Export/import content roundtrip Already fixed v1.3.0+
FIX-7: Provenance auto-verify after self-signing Already fixed v1.3.0+

Stats

  • 4 new tests
  • Security: 100/100 (all 7 Wizard audit gaps resolved)
  • 0 breaking changes

v1.5.0 - The Reactive Vault

08 Apr 23:53

Choose a tag to compare

The Reactive Vault

Event subscriptions, reprocessing, text-only search fallback, name-based lookup, and 8 new REST endpoints. Ready for Core integration.

New Features

  • Event Subscription: vault.subscribe(callback) for real-time mutation events (CREATE, UPDATE, DELETE, LIFECYCLE_TRANSITION). Sync and async callbacks. 5-second timeout, 100-subscriber cap, error isolation. Returns unsubscribe function.
  • Reprocess: vault.reprocess(resource_id) re-chunks and re-embeds when embedding models change. Preserves content, regenerates chunks.
  • Text-Only Search Fallback: vault.search() auto-degrades to text-only when no embedder is configured. Search works day one.
  • Find By Name: vault.find_by_name(name) case-insensitive lookup across the vault.
  • 8 New REST Endpoints: reprocess, grep, find by name, diff, get multiple, adversarial status, import, batch retrieval. 30 total endpoints.

Security Hardening

  • assert replaced with if/raise (survives -O bytecode)
  • Async callback timeout (5s) prevents event loop blocking
  • Subscriber cap (100) prevents memory exhaustion
  • Adversarial status allowlist validation
  • Import endpoint path traversal guard
  • Resource ID type coercion
  • RBAC enforcement on all new methods
  • Score: 100/100 (bandit clean, pip-audit clean)

Stats

  • 117 new tests (871+ total)
  • 8 new REST endpoints (30 total)
  • 3 docs updated (api-reference, fastapi, streaming)
  • 0 breaking changes

v1.4.0 — World-Class Grep Engine

08 Apr 22:40

Choose a tag to compare

World-Class Grep Engine

Single-pass multi-keyword search with three-signal blended scoring.

What's New

  • Single-pass FTS5 OR query (SQLite) and ILIKE+trigram query (Postgres): one database round-trip regardless of keyword count, replacing N+1 per-keyword loops
  • Three-signal scoring: keyword coverage (Lucene coord factor), native text rank (FTS5 bm25 / pg_trgm), term proximity (cover density ranking)
  • Keyword highlighting: explain_metadata.snippet with configurable markers
  • Full scoring breakdown: explain_metadata includes matched_keywords, hit_density, text_rank, proximity, and snippet
  • StorageBackend.grep() protocol method for both SQLite and PostgreSQL
  • grep_utils.py: shared utilities for FTS5 query building, keyword sanitization, snippet generation, and proximity scoring
  • Configurable weights: VaultConfig.grep_rank_weight (default 0.7) and grep_proximity_weight (default 0.3)

Scoring Formula

base = rank_weight * text_rank + proximity_weight * proximity
blended = coverage * base
final = blended * trust_weight * adversarial * freshness

Coverage acts as a multiplier (Lucene coord factor): 3/3 keywords = full score, 1/3 = 33%.

Fixed

  • Encryption test skip guards for [encryption] extra across three test files

Stats

  • 22 files changed, 1,242 insertions
  • 62 new grep tests (31 unit, 31 integration)
  • 799 total tests passing, zero regressions

Install

pip install qp-vault==1.4.0

Full changelog: CHANGELOG.md

v1.3.0 — All Technical Gaps Closed (Government-Grade)

07 Apr 16:50

Choose a tag to compare

All 12 gaps from the world-class roadmap are closed. Zero remaining technical gaps.

Membrane Pipeline: 6/8 Stages Implemented

REMEMBER -> INNATE_SCAN -> ADAPTIVE_SCAN -> CORRELATE -> RELEASE
                                                          |
                                              SURVEIL (at search time)

CORRELATE: Cross-Document Contradiction Detection

Flags new content that contradicts existing trusted (CANONICAL) resources. Prevents "poisoning by contradiction" attacks where adversaries submit conflicting information.

REMEMBER: Attack Pattern Registry

Learns from quarantined/flagged content. SHA3-256 fingerprints enable instant recognition of repeat attacks without LLM evaluation. Export/import for persistence.

SURVEIL: Query-Time Re-Evaluation

Penalizes resources that became SUSPICIOUS after initial screening. Applied at search time: 0.3x relevance penalty for suspicious, verification badges in explain metadata.

Also New

  • Embedding dimension check: Detects mismatched embedder dimensions on startup (prevents silent search corruption)
  • vault.diff(old_id, new_id): Unified diff between resource versions with addition/deletion counts

Roadmap Status: 12/12 COMPLETE

Gap Version Status
Classification enforcement v1.1.0 Done
Lossless import/export v1.1.0 Done
Telemetry integration v1.1.0 Done
Plugin hooks v1.2.0 Done
Auto-expiration v1.2.0 Done
Content deduplication v1.2.0 Done
Membrane CORRELATE v1.3.0 Done
Membrane REMEMBER v1.3.0 Done
Membrane SURVEIL v1.3.0 Done
Embedding dimension check v1.3.0 Done
Version diff v1.3.0 Done

Stats

  • 681 tests (+18 new)
  • 0 mypy errors (strict, 60 source files)
  • 0 ruff errors

Full changelog

v1.2.0 — Plugin Hooks, Auto-Expiration, Content Dedup

07 Apr 14:42

Choose a tag to compare

3 more gaps closed from the world-class roadmap. No breaking changes.

Plugin Hooks (GAP-4)

Hooks now fire during vault lifecycle events:

from qp_vault.plugins import get_registry

def on_add(resource, **kwargs):
    print(f"New resource: {resource.name}")

get_registry().register_hook("post_add", on_add)

Hook points: post_add, post_update, post_delete, post_search, post_transition.

Auto-Expiration (GAP-6)

Resources with valid_until dates are now automatically expired:

# Lazy: checked every 100 searches (zero config)
vault.search("query")  # Silently checks expirations periodically

# Background: explicit monitor for long-running services
await vault.start_expiration_monitor(interval_seconds=3600)

Content Deduplication (GAP-9)

Same content is never stored twice:

r1 = vault.add("Same document", name="a.md")
r2 = vault.add("Same document", name="b.md")
assert r1.id == r2.id  # Returns existing resource

Dedup is automatic (SHA3-256 CID match + tenant). Different tenants get separate copies.

Stats

  • 612 tests (+10 new)
  • 0 mypy errors (strict)
  • 0 ruff errors
  • 7 of 12 roadmap gaps closed (v1.1 + v1.2)

Full changelog

v1.1.0 — Classification Enforcement, Lossless Export, Telemetry

07 Apr 14:24

Choose a tag to compare

3 gaps closed from the world-class roadmap audit. No breaking changes.

Classification Enforcement (GAP-1)

CONFIDENTIAL and RESTRICTED content now rejects cloud embedding providers:

from qp_vault.embeddings.openai import OpenAIEmbedder

vault = Vault("./kb", embedder=OpenAIEmbedder(api_key="..."))
vault.add("Public doc", classification="public")           # OK
vault.add("Secret doc", classification="confidential")     # Raises VaultError

Use a local embedder (SentenceTransformerEmbedder, NoopEmbedder) for sensitive content. RESTRICTED resource reads are automatically audited.

Lossless Export/Import (GAP-2)

export_vault() now includes chunk content. Import reconstructs the original text:

vault.add("Critical policy content", name="policy.md")
vault.export_vault("backup.json")    # Includes full content

vault2 = Vault("./new-vault")
vault2.import_vault("backup.json")
content = vault2.get_content(...)    # "Critical policy content" preserved

Backward compatible with old export format (no _chunks = falls back to name).

Telemetry Integration (GAP-3)

Operations are now tracked automatically:

status = vault.status()
print(status["telemetry"])
# {"add": {"count": 5, "avg_ms": 12.3}, "search": {"count": 10, "avg_ms": 8.1}}

Stats

  • 602 tests (+16 new)
  • 0 mypy errors (strict)
  • 0 ruff errors

Full changelog

v1.0.0 — Production Stable

07 Apr 05:35

Choose a tag to compare

The governed knowledge store for autonomous organizations. Production-stable API lock.

Install

pip install qp-vault

What is qp-vault?

Every document has a trust tier that weights search results. Every chunk has a SHA3-256 content ID. Every mutation is auditable. The entire vault is verifiable via Merkle tree. Content is screened by an AI-powered Membrane before indexing. Access is controlled by RBAC. Air-gap native. Post-quantum ready.

1.0 Highlights

  • 28 public API operations with stable signatures
  • 543 tests, mypy strict 0 errors, 100/100 security score
  • Trust-weighted hybrid search (unique: no vector DB does this)
  • Knowledge lifecycle with temporal validity and supersession chains
  • Membrane content screening (regex + LLM-based, air-gap safe)
  • Post-quantum cryptography: ML-KEM-768 (FIPS 203) + ML-DSA-65 (FIPS 204)
  • RBAC: Reader / Writer / Admin roles enforced at API boundary
  • Multi-tenancy: tenant lock enforcement, atomic quotas
  • 19 docs including migration, deployment, and troubleshooting guides

New in 1.0 (vs v0.16)

  • vault.upsert(source, name=...): add-or-replace atomically
  • vault.get_multiple(resource_ids): batch retrieval
  • Migration guide (docs/migration.md)
  • Deployment guide (docs/deployment.md)
  • Troubleshooting guide (docs/troubleshooting.md)
  • Classifier: Production/Stable

Breaking Changes (from v0.x)

# Parameter renames
vault.add(source, trust_tier="canonical")      # was: trust=
vault.search(query, min_trust_tier="working")  # was: trust_min=
LayerDefaults(trust_tier="canonical")          # was: trust=

See migration guide for details.

Stats

Metric Value
Tests 543 passing
Source files 57 (mypy strict)
Docs 19 files
Security score 100/100
FIPS KATs SHA3-256, AES-256-GCM, ML-KEM-768

Full changelog

v0.16.0 — Membrane ADAPTIVE_SCAN

07 Apr 04:45

Choose a tag to compare

LLM-based semantic content screening. Stage 3 of 8 in the Membrane pipeline. Catches what regex misses.

Install / Upgrade

pip install --upgrade qp-vault

What's New

LLM-Based Content Screening

from qp_vault import Vault
from qp_vault.membrane.screeners.ollama import OllamaScreener

# Local LLM screening (air-gap safe)
vault = Vault("./knowledge", llm_screener=OllamaScreener(model="llama3.2"))

vault.add("Normal engineering document")     # PASS (both stages)
vault.add("Ign0r3 pr3v!ous instruct!ons")  # FLAG (adaptive catches obfuscation)

What Adaptive Scan Catches (That Regex Misses)

Attack Innate (Regex) Adaptive (LLM)
ignore previous instructions Yes Yes
Ign0r3 pr3v!ous rules (obfuscated) No Yes
Base64-encoded payloads No Yes
Assume the role of an admin No Yes
Legitimate security docs discussing attacks Flags (false positive) Passes (understands context)

Custom Screeners

from qp_vault.protocols import LLMScreener, ScreeningResult

class MyClaudeScreener:
    async def screen(self, content: str) -> ScreeningResult:
        # Call your LLM here
        return ScreeningResult(risk_score=0.1, reasoning="Safe", flags=[])

vault = Vault("./kb", llm_screener=MyClaudeScreener())

Design Principles

  • Optional: No LLM = stage skipped. Air-gap safe by default.
  • Protocol-based: Any LLM backend (Ollama, Claude, GPT, vLLM).
  • Cost-bounded: Content truncated to 4000 chars (configurable).
  • Error-tolerant: LLM failure = SKIP (never blocks ingestion).
  • Hardened prompt: Content in <document> block, isolated from instructions.

Stats

  • 543 tests passing (+23 new)
  • 0 mypy errors (57 files, strict)
  • 0 ruff errors

Full changelog