Tennant Guard (10-grd)
Tenant isolation primitives for developers building agentic tools in any environment.
GRD keeps the authenticated tenant scope attached to protected data operations. Its Z3 engine checks whether a supported selector can include foreign-owned or unlabeled data. The guarded client adds tenant scope, checks before execution, and validates complete result batches before returning them.
This is a standalone project with its own audience and architecture. It has no dependency on invariant-sast or AWS.
Install from source
Requires Python 3.10 or later:
git clone https://github.com/Ikurira/10_grd.git
cd 10_grd
python -m pip install -e ".[dev]"
python -m pytest
python examples/agent_memory.py
The distribution is named ten-grd; the Python import is ten_grd.
This repository does not imply that a release has been published to PyPI.
Use in an agent memory tool
from ten_grd import InMemoryAdapter, TenantContext, TenantGuard, tenant_scope
memory = TenantGuard(InMemoryAdapter())
# Your host authenticates the subject and validates tenant membership first.
with tenant_scope(TenantContext("acme", "alice", "request-1")):
memory.put("plan", {"text": "Acme's private plan"}, metadata={"kind": "plan"})
assert memory.get("plan").data["text"] == "Acme's private plan"
with tenant_scope(TenantContext("other", "bob", "request-2")):
assert memory.get("plan") is None
Tenant IDs in these examples are already authenticated by the host. Constructing TenantContext validates identifier format; it does not authenticate a user or establish tenant membership. Never construct it from an unchecked prompt, tool argument, or request field.
Tool implementations can call memory.get, search, put, and delete
inside the host-established scope. A tool argument cannot override the tenant
parameter because the guarded methods expose no such parameter.
Try tenant-scoped RAG
Run a local vector retrieval and answer assembly example without API keys:
python -m pip install -e ".[qdrant]"
python examples/tenant_rag.py
The example seeds two tenants with the same document ID. A foreign document has the closest vector, but only the active tenant's document reaches the answer. It also demonstrates an OR expression attempting to widen access and an explicit foreign-tenant selector returning no documents. Fixed vectors and extractive answers keep the demo reproducible; production embeddings and LLM generation remain host integrations. Retrieved content is still untrusted input.
See the developer adoption roadmap for release priorities. The local validation report records tested versions, results, and outstanding live-service coverage.
Selectors and formal checks
from ten_grd import Eq, Or, VerificationStatus, Z3InvariantEngine
engine = Z3InvariantEngine(timeout_ms=1000)
context = TenantContext("acme", "alice", "request-3")
safe = engine.verify_selector(context, Eq("tenant_id", "acme"))
assert safe.status is VerificationStatus.PROVEN
unsafe = engine.verify_selector(
context, Or((Eq("tenant_id", "acme"), Eq("tenant_id", "other")))
)
assert unsafe.status is VerificationStatus.VIOLATION
The public selector language supports Eq, And, Or, and Not over string metadata.
Missing fields are modeled explicitly. Raw SQL, filter strings, caller-supplied
filter_applied flags, and unsupported expression types are not security evidence.
The guarded client always places user selectors beneath its own tenant predicate. A user selector that requests another tenant returns no data; it never replaces the mandatory tenant restriction.
What this release protects
The included in-memory adapter provides atomic, tenant-partitioned create/replace, read, search, and delete operations. Record ownership is separate from user data. Payloads are JSON snapshots; reserved metadata cannot override tenant identity. Context uses contextvars; the engine creates a separate Z3 context per check.
Only PROVEN permits execution. SAT is a violation; UNKNOWN (including solver timeouts), unsupported expressions, and errors deny. Result validation occurs before returning a batch. There is no runtime soft-fail option.
Assurance boundary
A proof applies to the supported selector model. It does not prove arbitrary agent code, backend implementations, prompts, or deployment security. An empty selector can be safely unsatisfiable; this is not evidence of useful access.
The host authentication boundary, enforcement client, and storage adapter are trusted. An in-process SDK cannot prevent hostile application code from using raw credentials or bypassing the client. Custom adapters must execute exactly the checked operation and uphold ownership atomically. Read-result validation cannot undo an unsafe write by a faulty adapter.
Version 0.2 adds SQLite/PostgreSQL storage, Qdrant retrieval, Redis exact caching, Qdrant semantic caching, and LangChain tools. See integration setup and assurance boundaries. Authentication remains the host responsibility. See the specification and the threat model for extension requirements.
Incident-inspired regression requirements
The security regression guide uses verified Spring AI filter-injection and LiteLLM cache-isolation advisories to define general attack patterns and adapter acceptance criteria. These are regression guides, not claims of complete CVE mitigation or certification of affected third-party products.
Integrations
Install optional backends with python -m pip install -e ".[all]".
See the integration guide for usage, supported semantics,
server-backed test setup, and deployment requirements.
Development
python -m pip install -e ".[dev]"
python -m pytest -q
python -m compileall -q src examples
Tests cover foreign access, tenant scope injection, result leakage, write partitioning, async/thread isolation, inconclusive solvers, evidence binding, immutable snapshots, and differential checks of generated selector expressions.
Licensed under Apache-2.0.
Metadata
Release files for ten-grd 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| ten_grd-0.2.1.tar.gz | 30.6 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| ten_grd-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 58.4 kB
Release files / ten_grd-0.2.1.tar.gz
| Download URL | ten_grd-0.2.1.tar.gz |
|---|---|
| Size | 30.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
185348e68e0700134a37f55ef18b7a482d37a0f56997f138d2f7c88ae72ab58c
|
|
BLAKE2b-256 checksum How to use checksums |
49c1576825f2d7be6cf4ba3b4c60ad94dc5ece74f1befb80cd61911ccd15bf98
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logRelease files / ten_grd-0.2.1-py3-none-any.whl
| Download URL | ten_grd-0.2.1-py3-none-any.whl |
|---|---|
| Size | 27.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bdaea2e53e3302d8fe910070e1074ca8dfe8c108ba1c6ef29cfdc977c9135593
|
|
BLAKE2b-256 checksum How to use checksums |
22899ca02b9c5af40b02bfe7138c1d82c4b8d8b73d8eeef5f6dba58ffcf2c6e1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logSecurity for ten-grd 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for ten_grd-0.2.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.