Skip to content

Commit 75a89d7

Browse files
feat(vault): release v1.5.0 with event subscriptions, reprocess, security hardening
Event subscription system with sync/async callbacks, 5s timeout, 100-subscriber cap. Reprocess method for re-chunking/re-embedding. Text-only search fallback. Find by name lookup. 8 new REST endpoints (30 total). Security: assert->raise, callback timeout, subscriber cap, path traversal guard, adversarial allowlist, ID coercion, RBAC on all new methods. 117 new tests. 100/100 security score.
1 parent 98c1a31 commit 75a89d7

File tree

5 files changed

+58
-3
lines changed

5 files changed

+58
-3
lines changed

CHANGELOG.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
## [1.5.0] - 2026-04-08
11+
12+
### Added
13+
- **Event Subscription**: `vault.subscribe(callback)` registers sync or async callbacks for mutation events (CREATE, UPDATE, DELETE, LIFECYCLE_TRANSITION). Returns unsubscribe function. 5-second timeout on async callbacks. 100-subscriber cap. Error isolation: failing callbacks never block vault operations.
14+
- **Reprocess**: `vault.reprocess(resource_id)` re-chunks and re-embeds existing resources. Useful when embedding models change or chunking parameters are updated. Emits UPDATE subscriber event with `reprocessed=True`.
15+
- **Text-Only Search Fallback**: `vault.search()` automatically degrades to text-only mode (`vector_weight=0.0`, `text_weight=1.0`) when no embedder is configured. Search works on day one without requiring an embedding model.
16+
- **Find By Name**: `vault.find_by_name(name)` case-insensitive resource lookup. Returns first matching non-deleted resource or None.
17+
- **8 New REST Endpoints**: `POST /resources/{id}/reprocess`, `POST /grep`, `GET /resources/by-name`, `GET /resources/{old_id}/diff/{new_id}`, `POST /resources/multiple`, `PATCH /resources/{id}/adversarial`, `POST /import`, `GET /resources/by-name` (30 total endpoints).
18+
- 117 new tests across 6 test files (subscribe: 12, reprocess: 6, grep compat: 9, text fallback: 5, find_by_name: 5, integration: 46, security: 6, FastAPI: 15, cross-feature: 7, RBAC: 3, edge cases: 3)
19+
20+
### Security
21+
- Replaced `assert` statements with `if/raise VaultError` (survives optimized bytecode)
22+
- Subscriber callback timeout (5s via `asyncio.wait_for`) prevents event loop blocking
23+
- Subscriber cap (`_MAX_SUBSCRIBERS=100`) prevents memory exhaustion
24+
- Snapshot-copy of subscriber list before iteration prevents mutation during notify
25+
- Adversarial status endpoint validates against allowlist (`unverified`, `verified`, `suspicious`, `quarantined`)
26+
- Import endpoint rejects path traversal (`..` in path components)
27+
- `get_multiple` endpoint coerces all IDs to strings (prevents type confusion)
28+
- `find_by_name` enforces RBAC `search` permission
29+
- Security score: 100/100 (bandit clean, pip-audit clean)
30+
31+
### Changed
32+
- Total tests: 871+ (up from 520 at v1.3.0)
33+
- REST endpoints: 30 (up from 22)
34+
- Documentation updated: api-reference.md, fastapi.md, streaming-and-telemetry.md
35+
1036
## [1.4.0] - 2026-04-08
1137

1238
### Added

RELEASE_v1.5.0.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# The Reactive Vault
2+
3+
Event subscriptions, reprocessing, text-only search fallback, name-based lookup, and 8 new REST endpoints. Ready for Core integration.
4+
5+
## New Features
6+
7+
- **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.
8+
- **Reprocess**: `vault.reprocess(resource_id)` re-chunks and re-embeds when embedding models change. Preserves content, regenerates chunks.
9+
- **Text-Only Search Fallback**: `vault.search()` auto-degrades to text-only when no embedder is configured. Search works day one.
10+
- **Find By Name**: `vault.find_by_name(name)` case-insensitive lookup across the vault.
11+
- **8 New REST Endpoints**: reprocess, grep, find by name, diff, get multiple, adversarial status, import, batch retrieval. 30 total endpoints.
12+
13+
## Security Hardening
14+
15+
- `assert` replaced with `if/raise` (survives `-O` bytecode)
16+
- Async callback timeout (5s) prevents event loop blocking
17+
- Subscriber cap (100) prevents memory exhaustion
18+
- Adversarial status allowlist validation
19+
- Import endpoint path traversal guard
20+
- Resource ID type coercion
21+
- RBAC enforcement on all new methods
22+
- Score: 100/100 (bandit clean, pip-audit clean)
23+
24+
## Stats
25+
26+
- 117 new tests (871+ total)
27+
- 8 new REST endpoints (30 total)
28+
- 3 docs updated (api-reference, fastapi, streaming)
29+
- 0 breaking changes

docs/api-reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# API Reference
22

3-
Complete Python SDK for qp-vault v1.4.0.
3+
Complete Python SDK for qp-vault v1.5.0.
44

55
## Constructor
66

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "qp-vault"
7-
version = "1.4.0"
7+
version = "1.5.0"
88
description = "Governed knowledge store for autonomous organizations. Trust tiers, cryptographic audit trails, content-addressed storage, air-gap native."
99
readme = "README.md"
1010
license = "Apache-2.0"

src/qp_vault/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
Docs: https://github.com/quantumpipes/vault
2727
"""
2828

29-
__version__ = "1.4.0"
29+
__version__ = "1.5.0"
3030
__author__ = "Quantum Pipes Technologies, LLC"
3131
__license__ = "Apache-2.0"
3232

0 commit comments

Comments
 (0)