Skip to content

Security Integration

Dual-Model Security Architecture

ContextUnity enforces a strict “Token as Single Point of Truth (SPOT)” security model based on Per-Project Signing & Token Isolation.

There are two operation modes, automatically detected at startup:

1. Open Source Mode (HMAC Keystream)

Used when deploying independent projects without the centralized Enterprise Shield.

  • Config: CU_PROJECT_SECRET (unique per project).
  • Backend: HmacBackend (stdlib HMAC-SHA256).
  • Flow: The project’s ContextUnity SDK hashes its manifest against CU_PROJECT_SECRET to mint an ephemeral registration token. The Router verifies this using its own CU_PROJECT_SECRET. No Redis lookup of project secrets is performed.

2. Enterprise Mode (Shield Session Tokens)

Used in large, multi-tenant deployments managed by contextunity.shield.

  • Config: CU_SHIELD_GRPC_URL is set.
  • Backend: SessionTokenBackend (Ed25519).
  • Flow: Projects establish a zero-trust binding to Shield. A project’s tools and permissions are registered out-of-band by an Infrastructure Operator using the Admin CLI (uv run python -m contextunity.core.cli.admin sync-policy manifest.yaml). At runtime, Shield issues a short-lived Session Token signed with its private Ed25519 node key. All services verify the token instantly using Shield’s public key, without database lookups. Permissions are strictly controlled by the Shield Policy Engine, not self-declared by the project.

There is no UnsignedBackend or SECURITY_ENFORCEMENT toggle. Security is always enforced.

Universal Capability Stripping (Manifest-Driven ABAC)

ContextUnity implements zero-trust execution boundaries at the node level via Universal Capability Stripping. When a LangGraph node or tool is executed by contextunity.router:

  1. Manifest Parsing: The router reads the node’s declarative contextunity.project.yaml definition.
  2. Scope Derivation: It calculates the absolute minimum permissions needed (e.g., shield:secrets:read:<tenant>/api_keys/MY_MODEL_KEY, privacy:anonymize, tool:my_tool).
  3. Token Attenuation: The router invokes TokenBuilder().attenuate() right before calling the node’s function, stripping all other privileges from the in-memory ContextToken and appending the node’s name (>node:model_executor) to the cryptographically signed provenance chain.

This guarantees that even if an execution node is compromised via prompt injection, it cannot read other project secrets via contextunity.shield or execute unauthorized tools, enforcing a true Least-Privilege Architecture inside the router.

Derived Permissions

Under the Manifest-First architecture, permissions are Derived Permissions. If a project’s contextunity.project.yaml declares that it uses a specific LLM and a specific federated tool, the SDK’s ProjectBootstrapConfig and the Router’s registration compilation automatically compute the required permission scopes and grant them to the ContextToken. You do not need to manually configure or document these low-level string grants unless you are developing a new core platform service.

Token Handling & Interceptors

Server-side: SecurityGuard + ServicePermissionInterceptor

Each service constructs its own ServicePermissionInterceptor with a service-specific RPC_PERMISSION_MAP. See contextunity.router.service.interceptors or contextunity.brain.service.interceptors for examples.

import grpc
from contextunity.core import (
ServicePermissionInterceptor, # Server-side: checks per-RPC permissions
get_security_guard, # Token validation, Shield firewall
TokenMetadataInterceptor, # Client-side: injects token into metadata
)
# In handler: validate token and Shield checks
guard = get_security_guard()
async def MyMethod(self, request, context):
token = guard.validate_token(context)
result = await guard.check_input(user_input)
if result.blocked:
context.abort(grpc.StatusCode.PERMISSION_DENIED, result.reason)

Client-side: TokenMetadataInterceptor

from contextunity.core import TokenMetadataInterceptor
interceptor = TokenMetadataInterceptor(token)
channel = grpc.aio.insecure_channel("brain:50051", interceptors=[interceptor])

Auth Backends

The SDK uses AuthBackend for token attachment. Verification happens service-side.

from contextunity.core import (
AuthBackend, # Protocol
HmacBackend, # Open Source: HMAC-SHA256
SessionTokenBackend, # Enterprise: Ed25519 signed by Shield
get_signing_backend,
set_signing_backend,
)
# Backend is set at bootstrap (bootstrap_django / bootstrap_standalone)
backend = get_signing_backend()
metadata = backend.create_grpc_metadata(token) # For gRPC calls
BackendModeConfig Trigger
HmacBackendOpen SourceShield disabled + CU_PROJECT_SECRET
SessionTokenBackendEnterpriseservices.shield.enabled in manifest + CU_SHIELD_GRPC_URL

Redis Integrity Protection (Encrypt-then-MAC)

ContextUnity uses Redis for service discovery, ephemeral registration state, caching, and session coordination. Redis itself does not store project HMAC or session secrets in v1alpha8; those are resolved from environment variables (CU_PROJECT_SECRET) or fetched from contextunity.shield at verification time.

Required Configuration for all ContextUnity platform services (Router, Brain, Worker, View, etc.):

Terminal window
REDIS_URL=redis://localhost:6379/0

For externally hosted Redis, use TLS:

Terminal window
REDIS_URL=rediss://redis.example.com:6379/0

Note on legacy REDIS_SECRET_KEY: Earlier versions supported at-rest encryption of project secrets stored in Redis. v1alpha8 retires that store; project key material now comes from env or Shield. The old key variable is ignored by platform services and should be removed from deployment templates.

Service Discovery & Project Registry

To prevent tenant spoofing (“Tenant B claiming to be Project A’s owner”), ContextUnity relies on cryptographically signed ContextTokens and Shield policy.

  1. Token Verification (Anti-Spoofing): Every gRPC request carries a signed token. Services verify the signature against CU_PROJECT_SECRET (HMAC) or Shield’s Ed25519 public key, then enforce that the token’s allowed_tenants cover the requested resource.
  2. Service Discovery: Allows gRPC nodes to find each other dynamically via Redis without hardcoded IPs.

For the full implementation guide, fallback mechanisms, and Redis configuration, see Project Registry & Discovery.

Migrating from Open-Source (HMAC) to Enterprise (Shield)

To upgrade a project to the contextunity.shield zero-trust architecture:

  1. Deploy the contextunity.shield service and point CU_SHIELD_GRPC_URL in the Router/Brain/Worker templates to it.
  2. Create the project in Shield. This generates the Ed25519 keypair and an admin token:
    Terminal window
    contextshield project-create my-project \
    --permissions "brain:read,brain:write,router:execute"
    # Output includes admin_token — save it to Ansible vault
  3. Use the admin token to manage project permissions remotely (no SHIELD_MASTER_KEY needed):
    Terminal window
    contextshield project-policy my-project \
    --admin-token "shield-admin:my-project:Token..." \
    --permissions "brain:read,brain:write,router:execute"
  4. Set CU_SHIELD_GRPC_URL in the project’s own .env.

As soon as the SDK detects CU_SHIELD_GRPC_URL, it will automatically switch to the SessionTokenBackend handshake flow.

Open Source Mode (HMAC Keystream)

Used when deploying independent projects without the centralized Enterprise Shield.

  • Config: CU_PROJECT_SECRET (unique per project).
  • Backend: HmacBackend (stdlib HMAC-SHA256).
  • Flow: The project’s ContextUnity SDK hashes its manifest against CU_PROJECT_SECRET to mint an ephemeral registration token. The Router verifies this using its own CU_PROJECT_SECRET. No Redis lookup of project secrets is performed.

Enterprise Mode (Shield Session Tokens)

Used in large, multi-tenant deployments managed by contextunity.shield.

  • Config: CU_SHIELD_GRPC_URL is set.
  • Backend: SessionTokenBackend (Ed25519).
  • Flow: Projects establish a zero-trust binding to Shield. A project’s tools and permissions are registered out-of-band by an Infrastructure Operator using the Admin CLI (uv run python -m contextunity.core.cli.admin sync-policy manifest.yaml). At runtime, Shield issues a short-lived Session Token signed with its private Ed25519 node key. All services verify the token instantly using Shield’s public key, without database lookups. Permissions are strictly controlled by the Shield Policy Engine, not self-declared by the project.

There is no UnsignedBackend or SECURITY_ENFORCEMENT toggle. Security is always enforced.

gRPC TLS

from contextunity.core.grpc_utils import create_channel_sync, create_channel
# TLS is automatically enabled if GRPC_TLS_ENABLED=true or the URL starts with grpcs://
channel = create_channel_sync("brain.local:50051")