vaultcompute 0.1.0a1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vaultcompute-0.1.0a1/.gitignore +67 -0
- vaultcompute-0.1.0a1/CHANGELOG.md +57 -0
- vaultcompute-0.1.0a1/CONTRIBUTING.md +34 -0
- vaultcompute-0.1.0a1/LICENSE +21 -0
- vaultcompute-0.1.0a1/PKG-INFO +307 -0
- vaultcompute-0.1.0a1/README.md +278 -0
- vaultcompute-0.1.0a1/SECURITY.md +29 -0
- vaultcompute-0.1.0a1/docs/api.md +51 -0
- vaultcompute-0.1.0a1/docs/architecture.md +514 -0
- vaultcompute-0.1.0a1/docs/host-adapters.md +159 -0
- vaultcompute-0.1.0a1/docs/modes.md +407 -0
- vaultcompute-0.1.0a1/docs/pilot.md +88 -0
- vaultcompute-0.1.0a1/docs/release.md +123 -0
- vaultcompute-0.1.0a1/docs/roadmap.md +38 -0
- vaultcompute-0.1.0a1/docs/spikes/inbound-prompt-ner.md +64 -0
- vaultcompute-0.1.0a1/examples/__init__.py +0 -0
- vaultcompute-0.1.0a1/examples/demo_chat.py +145 -0
- vaultcompute-0.1.0a1/examples/fake_hr_mcp/__init__.py +0 -0
- vaultcompute-0.1.0a1/examples/fake_hr_mcp/__main__.py +87 -0
- vaultcompute-0.1.0a1/examples/quickstart.py +53 -0
- vaultcompute-0.1.0a1/examples/try_modes.py +348 -0
- vaultcompute-0.1.0a1/plugin/.claude-plugin/plugin.json +10 -0
- vaultcompute-0.1.0a1/plugin/.mcp.json +8 -0
- vaultcompute-0.1.0a1/plugin/README.md +146 -0
- vaultcompute-0.1.0a1/plugin/hooks/hooks.json +34 -0
- vaultcompute-0.1.0a1/plugins/vaultcompute-codex/.codex-plugin/plugin.json +24 -0
- vaultcompute-0.1.0a1/plugins/vaultcompute-codex/.mcp.json +8 -0
- vaultcompute-0.1.0a1/plugins/vaultcompute-codex/README.md +50 -0
- vaultcompute-0.1.0a1/plugins/vaultcompute-codex/hooks/hooks.json +37 -0
- vaultcompute-0.1.0a1/pyproject.toml +88 -0
- vaultcompute-0.1.0a1/scripts/package_smoke.py +94 -0
- vaultcompute-0.1.0a1/scripts/verify_claude_code.py +226 -0
- vaultcompute-0.1.0a1/scripts/verify_package.py +162 -0
- vaultcompute-0.1.0a1/scripts/verify_testpypi.py +64 -0
- vaultcompute-0.1.0a1/src/vaultcompute/__init__.py +18 -0
- vaultcompute-0.1.0a1/src/vaultcompute/__main__.py +3 -0
- vaultcompute-0.1.0a1/src/vaultcompute/audit.py +253 -0
- vaultcompute-0.1.0a1/src/vaultcompute/cli.py +224 -0
- vaultcompute-0.1.0a1/src/vaultcompute/config.py +354 -0
- vaultcompute-0.1.0a1/src/vaultcompute/core/__init__.py +0 -0
- vaultcompute-0.1.0a1/src/vaultcompute/core/capabilities.py +60 -0
- vaultcompute-0.1.0a1/src/vaultcompute/core/compute_attempts.py +39 -0
- vaultcompute-0.1.0a1/src/vaultcompute/core/lineage.py +86 -0
- vaultcompute-0.1.0a1/src/vaultcompute/core/policy.py +29 -0
- vaultcompute-0.1.0a1/src/vaultcompute/core/protection.py +69 -0
- vaultcompute-0.1.0a1/src/vaultcompute/core/rehydrator.py +79 -0
- vaultcompute-0.1.0a1/src/vaultcompute/core/sqlite_store.py +463 -0
- vaultcompute-0.1.0a1/src/vaultcompute/core/table.py +178 -0
- vaultcompute-0.1.0a1/src/vaultcompute/core/tokenizer.py +293 -0
- vaultcompute-0.1.0a1/src/vaultcompute/core/vault.py +188 -0
- vaultcompute-0.1.0a1/src/vaultcompute/errors.py +5 -0
- vaultcompute-0.1.0a1/src/vaultcompute/hooks.py +102 -0
- vaultcompute-0.1.0a1/src/vaultcompute/hosts/__init__.py +15 -0
- vaultcompute-0.1.0a1/src/vaultcompute/hosts/claude_code.py +191 -0
- vaultcompute-0.1.0a1/src/vaultcompute/hosts/codex.py +139 -0
- vaultcompute-0.1.0a1/src/vaultcompute/hosts/common.py +95 -0
- vaultcompute-0.1.0a1/src/vaultcompute/mcp_server.py +198 -0
- vaultcompute-0.1.0a1/src/vaultcompute/ports/__init__.py +0 -0
- vaultcompute-0.1.0a1/src/vaultcompute/ports/policy.py +24 -0
- vaultcompute-0.1.0a1/src/vaultcompute/ports/sandbox.py +19 -0
- vaultcompute-0.1.0a1/src/vaultcompute/ports/token_store.py +68 -0
- vaultcompute-0.1.0a1/src/vaultcompute/proxy.py +467 -0
- vaultcompute-0.1.0a1/src/vaultcompute/py.typed +0 -0
- vaultcompute-0.1.0a1/src/vaultcompute/sandbox/__init__.py +0 -0
- vaultcompute-0.1.0a1/src/vaultcompute/sandbox/subprocess_.py +136 -0
- vaultcompute-0.1.0a1/src/vaultcompute/session.py +120 -0
- vaultcompute-0.1.0a1/src/vaultcompute/tools/__init__.py +0 -0
- vaultcompute-0.1.0a1/src/vaultcompute/tools/vault_compute.py +182 -0
- vaultcompute-0.1.0a1/src/vaultcompute/tools/vault_table.py +163 -0
- vaultcompute-0.1.0a1/tests/__init__.py +0 -0
- vaultcompute-0.1.0a1/tests/e2e/__init__.py +0 -0
- vaultcompute-0.1.0a1/tests/e2e/recorded_transcript.json +14 -0
- vaultcompute-0.1.0a1/tests/e2e/test_demo_flow.py +100 -0
- vaultcompute-0.1.0a1/tests/e2e/test_mode_b_adversarial.py +109 -0
- vaultcompute-0.1.0a1/tests/integration/__init__.py +0 -0
- vaultcompute-0.1.0a1/tests/integration/test_host_plugin_contracts.py +70 -0
- vaultcompute-0.1.0a1/tests/integration/test_proxy_forwarding.py +183 -0
- vaultcompute-0.1.0a1/tests/unit/__init__.py +0 -0
- vaultcompute-0.1.0a1/tests/unit/test_architecture_boundaries.py +41 -0
- vaultcompute-0.1.0a1/tests/unit/test_audit.py +236 -0
- vaultcompute-0.1.0a1/tests/unit/test_capabilities.py +58 -0
- vaultcompute-0.1.0a1/tests/unit/test_cli.py +132 -0
- vaultcompute-0.1.0a1/tests/unit/test_codex_hooks.py +141 -0
- vaultcompute-0.1.0a1/tests/unit/test_config.py +456 -0
- vaultcompute-0.1.0a1/tests/unit/test_hooks.py +665 -0
- vaultcompute-0.1.0a1/tests/unit/test_host_common.py +13 -0
- vaultcompute-0.1.0a1/tests/unit/test_lineage.py +64 -0
- vaultcompute-0.1.0a1/tests/unit/test_mcp_server.py +187 -0
- vaultcompute-0.1.0a1/tests/unit/test_policy.py +71 -0
- vaultcompute-0.1.0a1/tests/unit/test_protection.py +67 -0
- vaultcompute-0.1.0a1/tests/unit/test_proxy_pumps.py +313 -0
- vaultcompute-0.1.0a1/tests/unit/test_public_api.py +25 -0
- vaultcompute-0.1.0a1/tests/unit/test_rehydrator.py +107 -0
- vaultcompute-0.1.0a1/tests/unit/test_review_regressions.py +166 -0
- vaultcompute-0.1.0a1/tests/unit/test_sandbox.py +242 -0
- vaultcompute-0.1.0a1/tests/unit/test_session.py +241 -0
- vaultcompute-0.1.0a1/tests/unit/test_table.py +473 -0
- vaultcompute-0.1.0a1/tests/unit/test_token_store_conformance.py +441 -0
- vaultcompute-0.1.0a1/tests/unit/test_tokenizer.py +229 -0
- vaultcompute-0.1.0a1/tests/unit/test_vault.py +171 -0
- vaultcompute-0.1.0a1/tests/unit/test_vault_compute.py +319 -0
- vaultcompute-0.1.0a1/uv.lock +1049 -0
- vaultcompute-0.1.0a1/vaultcompute.example.yaml +70 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
|
|
8
|
+
# Virtual envs
|
|
9
|
+
.venv/
|
|
10
|
+
venv/
|
|
11
|
+
env/
|
|
12
|
+
|
|
13
|
+
# Packaging
|
|
14
|
+
build/
|
|
15
|
+
dist/
|
|
16
|
+
*.egg-info/
|
|
17
|
+
*.egg
|
|
18
|
+
|
|
19
|
+
# Tests / coverage
|
|
20
|
+
.pytest_cache/
|
|
21
|
+
.coverage
|
|
22
|
+
.coverage.*
|
|
23
|
+
htmlcov/
|
|
24
|
+
.tox/
|
|
25
|
+
.nox/
|
|
26
|
+
|
|
27
|
+
# Type checkers / linters
|
|
28
|
+
.mypy_cache/
|
|
29
|
+
.ruff_cache/
|
|
30
|
+
.pyright/
|
|
31
|
+
|
|
32
|
+
# Env / secrets
|
|
33
|
+
.env
|
|
34
|
+
.env.*
|
|
35
|
+
!.env.example
|
|
36
|
+
|
|
37
|
+
# Editors
|
|
38
|
+
.idea/
|
|
39
|
+
.vscode/
|
|
40
|
+
*.swp
|
|
41
|
+
.DS_Store
|
|
42
|
+
|
|
43
|
+
# VaultCompute local artifacts
|
|
44
|
+
vault.db
|
|
45
|
+
vault.db-wal
|
|
46
|
+
vault.db-shm
|
|
47
|
+
*.db-wal
|
|
48
|
+
*.db-shm
|
|
49
|
+
vaultcompute.yaml
|
|
50
|
+
vaultcompute-proxy.yaml
|
|
51
|
+
.mcp.json
|
|
52
|
+
*.vaultcompute.log
|
|
53
|
+
|
|
54
|
+
# Pre-rename local files may contain real schemas or secrets. Keep them ignored
|
|
55
|
+
# so an existing checkout cannot accidentally stage them during migration.
|
|
56
|
+
blindfold.yaml
|
|
57
|
+
blindfold-proxy.yaml
|
|
58
|
+
*.blindfold.log
|
|
59
|
+
|
|
60
|
+
# Local development scaffolding — tooling and scratch harnesses, not part of
|
|
61
|
+
# the project. Kept out of the repo deliberately: they belong to one machine
|
|
62
|
+
# and one workflow, and would rot here.
|
|
63
|
+
graphify-out/
|
|
64
|
+
.claude/
|
|
65
|
+
CLAUDE.md
|
|
66
|
+
examples/debug_walkthrough.py
|
|
67
|
+
examples/demo_chat_ollama.py
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to VaultCompute are documented here.
|
|
4
|
+
|
|
5
|
+
## 0.1.0a1 - 2026-09-14
|
|
6
|
+
|
|
7
|
+
First alpha of the Mode B library, with memory and SQLite storage, optional
|
|
8
|
+
encryption and the CLI. Mode A remains a beta proxy; Modes C/D are experimental
|
|
9
|
+
host adapters.
|
|
10
|
+
|
|
11
|
+
### Distribution
|
|
12
|
+
|
|
13
|
+
- MIT SPDX metadata and explicit source-archive contents.
|
|
14
|
+
- Clean wheel and source installs checked across the supported CI matrix.
|
|
15
|
+
- Manual, tag-bound Trusted Publishing through TestPyPI before PyPI.
|
|
16
|
+
- Runnable controlled-query demo, pilot protocol and private security reporting.
|
|
17
|
+
- Python selection in CI now explicitly follows the declared matrix.
|
|
18
|
+
|
|
19
|
+
### Security
|
|
20
|
+
|
|
21
|
+
- Strict Mode A and Claude Code reject protected MCP responses containing
|
|
22
|
+
unsupported `structuredContent`, which previously remained in cleartext.
|
|
23
|
+
- Resource schema merging preserves both full coverage and required-path
|
|
24
|
+
checks across overlapping globs, without nesting placeholders.
|
|
25
|
+
- Resource `tables` declarations are rejected at config load until supported;
|
|
26
|
+
use `sensitive_fields` to hide a resource's array as an opaque value.
|
|
27
|
+
- Hook vault initialization failures now emit the host's blocking response.
|
|
28
|
+
- Schema overlap validation now includes intersecting wildcards and indices.
|
|
29
|
+
|
|
30
|
+
## Development snapshot - 2026-09-04 (unpublished)
|
|
31
|
+
|
|
32
|
+
First public release candidate.
|
|
33
|
+
|
|
34
|
+
The project was renamed from its unpublished working name to **VaultCompute**;
|
|
35
|
+
the distribution, Python package, CLI, configuration file and operation tools
|
|
36
|
+
now use the `vaultcompute` / `vault_*` naming consistently.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- Fail-closed Mode B `VaultComputeSession` for synchronous and asynchronous tool
|
|
41
|
+
protection, exact capability-authorized table queries, model instructions and
|
|
42
|
+
final rendering.
|
|
43
|
+
- Strict Mode A stdio MCP proxy for declared JSON tool results and resources.
|
|
44
|
+
- Experimental Claude Code and Codex host adapters.
|
|
45
|
+
- Memory and SQLite token stores, with optional AES-256-GCM encryption at rest.
|
|
46
|
+
- Controlled collective-table operations and explicit `python_unsafe` compute.
|
|
47
|
+
- Session-bound policy, lineage, compute-attempt quotas and transcript audit.
|
|
48
|
+
|
|
49
|
+
### Security
|
|
50
|
+
|
|
51
|
+
- Required protected paths and strict unsupported-shape handling fail closed.
|
|
52
|
+
- Exact table capabilities bind session, table, complete operations and expiry.
|
|
53
|
+
- Adversarial Mode B tests cover shape drift, adaptive threshold changes,
|
|
54
|
+
forged placeholders and cross-session access.
|
|
55
|
+
|
|
56
|
+
Known structural and temporary limits are maintained in
|
|
57
|
+
[`LIMITATIONS.md`](LIMITATIONS.md).
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Start with a small, reproducible integration case. Use synthetic data and
|
|
4
|
+
include the Python/package versions and integration mode; host reports also
|
|
5
|
+
need the host version. Security issues belong in the private channel described
|
|
6
|
+
in [SECURITY.md](SECURITY.md).
|
|
7
|
+
|
|
8
|
+
## Local checks
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
uv sync --locked --all-extras --dev
|
|
12
|
+
uv run pytest
|
|
13
|
+
uv build --no-sources --out-dir dist/release
|
|
14
|
+
uv run python scripts/verify_package.py dist/release --install
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Use a fresh output directory when preparing a new version. The package verifier
|
|
18
|
+
rejects mixed or stale release artifacts. It installs the wheel and source
|
|
19
|
+
archive into temporary environments outside the checkout, with `PYTHONPATH`
|
|
20
|
+
removed, and exercises the public API, CLI and encrypted storage.
|
|
21
|
+
|
|
22
|
+
Changes to a privacy boundary need a failing regression case before the fix,
|
|
23
|
+
then both the focused tests and the full suite. Avoid tests that merely repeat
|
|
24
|
+
implementation details. Update the changelog and the supported-shape contract
|
|
25
|
+
when behavior changes. Real-host compatibility requires an actual host run;
|
|
26
|
+
fixtures are only a regression check.
|
|
27
|
+
|
|
28
|
+
For new features, explain the user task and why the current operations cannot
|
|
29
|
+
complete it. Preserve the separation between the core and host/transport
|
|
30
|
+
adapters, and keep raw values out of model-visible errors.
|
|
31
|
+
|
|
32
|
+
Release preparation and the pilot protocol live in [docs/release.md](docs/release.md)
|
|
33
|
+
and [docs/pilot.md](docs/pilot.md). Code is distributed under the repository's
|
|
34
|
+
[MIT license](LICENSE).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Manuel Pernigotto
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vaultcompute
|
|
3
|
+
Version: 0.1.0a1
|
|
4
|
+
Summary: Controlled computation over private data for LLM applications.
|
|
5
|
+
Project-URL: Homepage, https://github.com/ManuelPr/vaultcompute
|
|
6
|
+
Project-URL: Repository, https://github.com/ManuelPr/vaultcompute
|
|
7
|
+
Project-URL: Issues, https://github.com/ManuelPr/vaultcompute/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/ManuelPr/vaultcompute/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Documentation, https://github.com/ManuelPr/vaultcompute/blob/main/docs/api.md
|
|
10
|
+
Author: Manuel Pernigotto
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: llm,mcp,privacy,tokenization
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Requires-Dist: mcp<2,>=1.0
|
|
22
|
+
Requires-Dist: pydantic>=2.6
|
|
23
|
+
Requires-Dist: pyyaml>=6.0
|
|
24
|
+
Provides-Extra: demo
|
|
25
|
+
Requires-Dist: anthropic>=0.30; extra == 'demo'
|
|
26
|
+
Provides-Extra: encryption
|
|
27
|
+
Requires-Dist: cryptography>=42; extra == 'encryption'
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# VaultCompute
|
|
31
|
+
|
|
32
|
+
**Private data. Usable reasoning.**
|
|
33
|
+
|
|
34
|
+
VaultCompute is a Python privacy layer for structured LLM tool results. It
|
|
35
|
+
replaces declared private values with opaque tokens before your application
|
|
36
|
+
sends the result to a model. Real values remain in a local vault; your
|
|
37
|
+
application restores authorized values only when displaying the final answer.
|
|
38
|
+
|
|
39
|
+
Use it when an agent needs to filter, sort or aggregate private records without
|
|
40
|
+
putting those records in the model's context. Your application still owns tool
|
|
41
|
+
access, user authorization and the conversation loop.
|
|
42
|
+
|
|
43
|
+
**Status: alpha (`0.1.0a1`).** The library, MCP proxy, token stores and host adapters
|
|
44
|
+
are implemented. Host integrations are version-sensitive; test their supported
|
|
45
|
+
result shapes before relying on them. See [limitations](https://github.com/ManuelPr/vaultcompute/blob/main/LIMITATIONS.md).
|
|
46
|
+
|
|
47
|
+
## How it works
|
|
48
|
+
|
|
49
|
+
1. **Declare** sensitive fields or whole tables in a schema for each tool.
|
|
50
|
+
2. **Protect** the result: store private values in memory or SQLite and replace
|
|
51
|
+
them with fresh, opaque placeholders containing 128 random bits.
|
|
52
|
+
3. **Query** a hidden table with `vault_table`. Fixed operations return another
|
|
53
|
+
placeholder, with lineage and inherited restrictions.
|
|
54
|
+
4. **Render** the final answer for the user after authorization. Keep the
|
|
55
|
+
rendered cleartext out of subsequent model requests.
|
|
56
|
+
|
|
57
|
+
For example, a salary tool's result becomes `{"employees": "⟦tok_…⟧"}`. The
|
|
58
|
+
model can request a sort by salary and a limit of one row. It receives another
|
|
59
|
+
token; only final rendering reveals the selected employee. The abbreviated
|
|
60
|
+
placeholder here is illustrative; real placeholders must be copied verbatim.
|
|
61
|
+
|
|
62
|
+
The default `controlled` profile supports `filter`, `sort_by`, `limit`,
|
|
63
|
+
`select`, `sum`, `mean`, `min`, `max` and `count` over declared tables.
|
|
64
|
+
It executes no model-written code. Arbitrary Python through `vault_compute`
|
|
65
|
+
requires explicit `compute.mode: python_unsafe` opt-in and assumes a cooperative
|
|
66
|
+
model; it is not a safe boundary against malicious code or prompt injection.
|
|
67
|
+
|
|
68
|
+
## Quick start
|
|
69
|
+
|
|
70
|
+
Install from this repository with Python 3.11+ and `uv`:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
git clone https://github.com/ManuelPr/vaultcompute
|
|
74
|
+
cd vaultcompute
|
|
75
|
+
uv sync
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Alternatively, in your own Python environment, run `python -m pip install -e .`.
|
|
79
|
+
The commands below use `uv run` to select the project's environment.
|
|
80
|
+
|
|
81
|
+
Run `uv run python examples/quickstart.py`, or save the complete example below
|
|
82
|
+
as `quickstart.py` and run `uv run python quickstart.py`. It uses synthetic data and a scripted query;
|
|
83
|
+
no API key, model service or MCP server is required.
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
import json
|
|
87
|
+
import sys
|
|
88
|
+
from datetime import datetime, timedelta, timezone
|
|
89
|
+
from uuid import uuid4
|
|
90
|
+
|
|
91
|
+
from vaultcompute import TableQueryCapability, VaultComputeSession
|
|
92
|
+
from vaultcompute.config import VaultComputeConfig
|
|
93
|
+
|
|
94
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def list_employees():
|
|
98
|
+
return {"employees": [
|
|
99
|
+
{"name": "Manuel", "salary": 62000},
|
|
100
|
+
{"name": "Andrea", "salary": 71000},
|
|
101
|
+
]}
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
config = VaultComputeConfig.model_validate({
|
|
105
|
+
"schemas": {
|
|
106
|
+
"list_employees": {
|
|
107
|
+
"tables": [{
|
|
108
|
+
"path": "$.employees",
|
|
109
|
+
"columns": [{"name": "name"}, {"name": "salary"}],
|
|
110
|
+
}]
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
session = VaultComputeSession(config, session_id=uuid4().hex)
|
|
115
|
+
protected = session.call_protected_tool("list_employees", list_employees)
|
|
116
|
+
print("Tool result for the model:", json.dumps(protected, ensure_ascii=False))
|
|
117
|
+
|
|
118
|
+
# The trusted application authorizes this exact request: highest-paid employee.
|
|
119
|
+
ops = [
|
|
120
|
+
{"op": "sort_by", "column": "salary", "desc": True},
|
|
121
|
+
{"op": "limit", "n": 1},
|
|
122
|
+
{"op": "select", "columns": ["name", "salary"]},
|
|
123
|
+
]
|
|
124
|
+
capability = TableQueryCapability.issue(
|
|
125
|
+
session_id=session.session_id,
|
|
126
|
+
table_token=protected["employees"],
|
|
127
|
+
ops=ops,
|
|
128
|
+
expires_at=datetime.now(timezone.utc) + timedelta(minutes=5),
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
# Scripted stand-in for the model's proposed vault_table call.
|
|
132
|
+
proposed_query = {"table": protected["employees"], "ops": ops}
|
|
133
|
+
result_token = session.execute_authorized_query(
|
|
134
|
+
proposed_query, capability=capability,
|
|
135
|
+
)
|
|
136
|
+
model_answer = f"Highest-paid employee: {result_token}"
|
|
137
|
+
print("Model answer:", model_answer)
|
|
138
|
+
print("User sees:", session.render_final_answer(model_answer))
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The first two lines contain placeholders. The last line shows:
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
User sees: Highest-paid employee: [{"name": "Andrea", "salary": 71000}]
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
In a real integration, add `session.model_instructions` to the system prompt,
|
|
148
|
+
send only protected tool results to the model, and dispatch its proposed table
|
|
149
|
+
queries through the authorized handler. Issue capabilities from trusted
|
|
150
|
+
application decisions, not automatically from whatever query the model proposes.
|
|
151
|
+
Render only at the final user-facing boundary; never add that cleartext to model
|
|
152
|
+
history. Async tools use `await session.call_protected_tool_async(...)`.
|
|
153
|
+
|
|
154
|
+
The library does not supply an LLM conversation loop. See the
|
|
155
|
+
[Python API](https://github.com/ManuelPr/vaultcompute/blob/main/docs/api.md) for its supported methods and integration contract.
|
|
156
|
+
|
|
157
|
+
## Choose an integration
|
|
158
|
+
|
|
159
|
+
| Mode | Use it when | Status | Final values |
|
|
160
|
+
|---|---|---|---|
|
|
161
|
+
| **B — Python library** | You own the application and model loop | Reference integration | Your application renders them |
|
|
162
|
+
| **A — stdio MCP proxy** | You wrap one existing MCP server | Beta | Placeholders unless your client implements final rendering |
|
|
163
|
+
| **C — Claude Code plugin** | You use the supported host hook shapes | Experimental | Display-only reveal through the adapter |
|
|
164
|
+
| **D — Codex plugin** | You protect supported local tool results | Experimental guardrail | Placeholders remain visible |
|
|
165
|
+
|
|
166
|
+
Start with **Mode B** when you write the application. For Mode A, configure
|
|
167
|
+
your MCP client to launch the proxy with an explicit configuration path:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
uv run vaultcompute --config vaultcompute.yaml -- python -m your_org.some_mcp_server
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
The downstream command above is a placeholder for your own MCP server. The
|
|
174
|
+
proxy cannot intercept a third-party client's final answer for display.
|
|
175
|
+
|
|
176
|
+
For host setup, follow the [Claude Code plugin guide](https://github.com/ManuelPr/vaultcompute/blob/main/plugin/README.md) or the
|
|
177
|
+
[Codex plugin guide](https://github.com/ManuelPr/vaultcompute/blob/main/plugins/vaultcompute-codex/README.md). Both require a shared
|
|
178
|
+
SQLite vault and the `vaultcompute` command on the host's `PATH`.
|
|
179
|
+
The [host adapter contract](https://github.com/ManuelPr/vaultcompute/blob/main/docs/host-adapters.md) lists supported shapes,
|
|
180
|
+
failure behavior and real-host verification. Hook fixtures alone do not prove
|
|
181
|
+
compatibility with an installed host version.
|
|
182
|
+
|
|
183
|
+
## Configuration
|
|
184
|
+
|
|
185
|
+
The Python example above creates its configuration directly. For the CLI and
|
|
186
|
+
plugins, create `vaultcompute.yaml`; start from
|
|
187
|
+
[vaultcompute.example.yaml](https://github.com/ManuelPr/vaultcompute/blob/main/vaultcompute.example.yaml). A minimal declaration is:
|
|
188
|
+
|
|
189
|
+
```yaml
|
|
190
|
+
schemas:
|
|
191
|
+
get_salary:
|
|
192
|
+
sensitive_fields:
|
|
193
|
+
- path: $.salary
|
|
194
|
+
semantic_type: salary
|
|
195
|
+
unit: EUR/year
|
|
196
|
+
- path: $.bonus
|
|
197
|
+
required: false
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
- Tool names must match the names passed to the integration exactly.
|
|
201
|
+
- Paths are **required by default**. A missing required path stops protection;
|
|
202
|
+
`required: false` permits a legitimate absence. Unsupported path syntax and
|
|
203
|
+
overlapping declarations within one schema are rejected at load.
|
|
204
|
+
- A `tables` declaration hides the entire list. Its columns specify what the
|
|
205
|
+
model may query. Scalar placeholders are not queryable with `vault_table`.
|
|
206
|
+
- MCP `resources` use URI globs and support **`sensitive_fields` only**.
|
|
207
|
+
Resource `tables` declarations are rejected. An array can be hidden as a
|
|
208
|
+
sensitive field, but that does not make it a queryable table.
|
|
209
|
+
- `compute.mode` defaults to `controlled`; the proxy and host operation server
|
|
210
|
+
also accept `disabled` and the explicit `python_unsafe` profile.
|
|
211
|
+
|
|
212
|
+
### Storage and expiry
|
|
213
|
+
|
|
214
|
+
Memory storage is the default and loses its vault when the process ends.
|
|
215
|
+
Use SQLite when tokens must survive restarts or be shared across processes:
|
|
216
|
+
|
|
217
|
+
```yaml
|
|
218
|
+
storage:
|
|
219
|
+
backend: sqlite
|
|
220
|
+
path: ./vault.db
|
|
221
|
+
encrypt_at_rest: true
|
|
222
|
+
tokens:
|
|
223
|
+
default_ttl: 3600
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
For encryption, install the optional dependency from the repository:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
uv sync --extra encryption
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Or use `python -m pip install -e ".[encryption]"` in your own environment.
|
|
233
|
+
Encrypted storage requires `VAULTCOMPUTE_VAULT_KEY` in every process that opens
|
|
234
|
+
the vault: a base64-encoded 32-byte key, supplied outside the configuration and
|
|
235
|
+
database. Values are encrypted with AES-256-GCM; session and lineage metadata
|
|
236
|
+
remain readable. Without encryption enabled, SQLite stores cleartext values.
|
|
237
|
+
|
|
238
|
+
The default token lifetime is one hour. SQLite persistence does not extend it:
|
|
239
|
+
expired or unknown tokens render as `[unknown token]`; tokens denied by policy
|
|
240
|
+
render as `[redacted]`.
|
|
241
|
+
|
|
242
|
+
## Threat model & limitations
|
|
243
|
+
|
|
244
|
+
Protection applies to **declared values on supported result paths**. It does
|
|
245
|
+
not cover the entire conversation or replace your application's access control.
|
|
246
|
+
|
|
247
|
+
- **Undeclared values remain visible.** Review schemas whenever tools change.
|
|
248
|
+
User prompts, tool arguments and values sent through other application paths
|
|
249
|
+
are outside this protection.
|
|
250
|
+
- **Unsupported results are blocked on strict paths.** Mode A strict rejects
|
|
251
|
+
batches and protected results with non-JSON text, images, blobs or
|
|
252
|
+
`structuredContent`. The Claude Code MCP adapter also rejects
|
|
253
|
+
`structuredContent`. `proxy.strict: false` allows compatibility passthrough
|
|
254
|
+
and gives up that blocking guarantee.
|
|
255
|
+
- **Host coverage is limited.** Tools that do not enter an adapter's supported
|
|
256
|
+
hooks are not protected. Host telemetry may record original results before
|
|
257
|
+
a hook runs. The Codex adapter does not provide display-only rehydration.
|
|
258
|
+
- **The vault and final rendering are trusted.** Real values exist in process
|
|
259
|
+
memory. Session-bound policy is the default; application authorization must
|
|
260
|
+
decide which user may access the underlying data and approve a query.
|
|
261
|
+
- **Arbitrary Python is unsafe.** Its restricted subprocess and lineage-wide
|
|
262
|
+
attempt quota do not eliminate extraction through deliberate errors or
|
|
263
|
+
sandbox escapes. Table-derived tokens cannot be used as Python inputs.
|
|
264
|
+
- **Hidden values limit reasoning.** The model can request supported mechanical
|
|
265
|
+
operations, but cannot independently assess the meaning of an unseen value.
|
|
266
|
+
|
|
267
|
+
`vaultcompute audit` checks transcripts against live vault records for exact
|
|
268
|
+
cleartext matches and suspicious compute attempts. It is diagnostic evidence,
|
|
269
|
+
not proof of non-disclosure; undeclared, transformed or expired values can evade
|
|
270
|
+
the check. See [LIMITATIONS.md](https://github.com/ManuelPr/vaultcompute/blob/main/LIMITATIONS.md) for the detailed threat model.
|
|
271
|
+
|
|
272
|
+
## Development and next steps
|
|
273
|
+
|
|
274
|
+
From the repository:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
uv sync --all-extras --dev
|
|
278
|
+
uv run pytest
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
The CI workflow defines a test matrix for Linux, macOS and Windows on Python
|
|
282
|
+
3.11–3.13. Host compatibility also needs real-host verification.
|
|
283
|
+
|
|
284
|
+
The next release priorities are testing the built package in clean environments,
|
|
285
|
+
verifying supported host versions and exercising real integration cases.
|
|
286
|
+
Joins, group-by, HTTP transport and additional storage backends are possible
|
|
287
|
+
future work, not available features.
|
|
288
|
+
|
|
289
|
+
## Documentation and contributing
|
|
290
|
+
|
|
291
|
+
- [Python API](https://github.com/ManuelPr/vaultcompute/blob/main/docs/api.md): supported imports and the application boundary.
|
|
292
|
+
- [Integration modes](https://github.com/ManuelPr/vaultcompute/blob/main/docs/modes.md): detailed setup and tradeoffs.
|
|
293
|
+
- [Host adapters](https://github.com/ManuelPr/vaultcompute/blob/main/docs/host-adapters.md): exact coverage and compatibility checks.
|
|
294
|
+
- [Architecture](https://github.com/ManuelPr/vaultcompute/blob/main/docs/architecture.md): core, storage, policy and adapters.
|
|
295
|
+
- [Configuration example](https://github.com/ManuelPr/vaultcompute/blob/main/vaultcompute.example.yaml): supported YAML settings.
|
|
296
|
+
- [Limitations](https://github.com/ManuelPr/vaultcompute/blob/main/LIMITATIONS.md) and [changelog](https://github.com/ManuelPr/vaultcompute/blob/main/CHANGELOG.md).
|
|
297
|
+
- [Release procedure](https://github.com/ManuelPr/vaultcompute/blob/main/docs/release.md), [pilot guide](https://github.com/ManuelPr/vaultcompute/blob/main/docs/pilot.md) and [next-version criteria](https://github.com/ManuelPr/vaultcompute/blob/main/docs/roadmap.md).
|
|
298
|
+
- [Contributing](https://github.com/ManuelPr/vaultcompute/blob/main/CONTRIBUTING.md) and [private security reporting](https://github.com/ManuelPr/vaultcompute/blob/main/SECURITY.md).
|
|
299
|
+
|
|
300
|
+
Issues and pull requests are welcome. Useful contributions include reproducible
|
|
301
|
+
bugs, tests using synthetic data, schema examples and integration feedback.
|
|
302
|
+
Include the package version, integration mode and host version where relevant;
|
|
303
|
+
do not put real private data or vault keys in public reports.
|
|
304
|
+
|
|
305
|
+
## License
|
|
306
|
+
|
|
307
|
+
[MIT](https://github.com/ManuelPr/vaultcompute/blob/main/LICENSE). Copyright © 2026 Manuel Pernigotto.
|