Skip to main content

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.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for ten-grd 0.2.0
File Size Uploaded Provenance
ten_grd-0.2.0.tar.gz 30.6 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for ten-grd 0.2.0
File Interpreter ABI Platform
ten_grd-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 58.3 kB

Release files / ten_grd-0.2.0.tar.gz

Download URL ten_grd-0.2.0.tar.gz
Size 30.6 kB
Tags Source
SHA-256 checksum
How to use checksums
15a20adc45350b996e8d12862dc84b786bc3709bb40930245a54e8e17d130e2c
BLAKE2b-256 checksum
How to use checksums
23385405b580f2487aa33af9f68d9a4e15f21efef23b51d96809517d62d0980e
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 log

Release files / ten_grd-0.2.0-py3-none-any.whl

Download URL ten_grd-0.2.0-py3-none-any.whl
Size 27.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5cd20e46ee549b27bb43aaee5c2585c19222b3e376f1b58deda3c5baecacfe37
BLAKE2b-256 checksum
How to use checksums
f386fa786a03c7d371be95c918e1af1c0041b02dec3bbf3e7c13ad152e201899
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 log

Security for ten-grd 0.2.0

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.

Select from 2 files

Attestation for ten_grd-0.2.0.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 log

A 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.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page