Skip to content

ContextUnity Security Scope

ContextUnity uses stateless cryptographic tokens (ContextToken) to handle multi-tenancy and authentication without the need for central database lookups. The ecosystem supports two distinct signing approaches, balancing simplicity for internal networks against strict zero-trust security for enterprise deployments.

1. Open Source — Per-Project HMAC Signing

When all services belong to one organization and projects connect to a shared Router, the simplest approach is per-project HMAC signing.

This model is built-in to the open-source contextunity.core package and requires no third-party dependencies (stdlib only).

How It Works

  1. Project Secret: Each project generates its own CU_PROJECT_SECRET using the built-in CLI: python -m contextunity.core.cli.mint hmac.
  2. Bootstrap: On startup, contextunity.core.sdk.bootstrap.bootstrap_django() (or bootstrap_standalone()) auto-detects CU_PROJECT_SECRET in the environment and creates an HmacBackend. It then calls set_signing_backend(backend) to cache it as a singleton.
  3. Registration: The project sends a RegisterManifest gRPC to the Router. The bundle includes the project_secret, which the Router stores encrypted in Redis (via REDIS_SECRET_KEY).
  4. Signing: For all subsequent calls, the project creates a ContextToken with a composite kid (e.g., myproject:hmac-v1) and signs it with its own HMAC secret.
  5. Verification: The Router’s ServicePermissionInterceptor parses the composite kid, fetches the project’s encrypted secret from Redis via get_project_key(), builds an HmacBackend, and verifies the signature.

Per-Project Isolation

Each project has its own unique secret. A compromised project cannot forge tokens for other projects — the Router verifies each token against the project’s individually stored secret.


2. Enterprise — contextunity.shield (Asymmetric Ed25519 + Session Tokens)

For enterprise scenarios where multiple distinct organizations, third parties, or isolated microservices connect to one unified Brain & Router, the per-project HMAC model can be upgraded to asymmetric signing via contextunity.shield.

contextunity.shield provides a centralized security authority that guarantees a compromised project can never forge tokens for other tenants.

How It Works

  1. Shield as Authority: contextunity.shield maintains a per-project Ed25519 key pair database. Projects authenticate to Shield using their CU_PROJECT_SECRET (project identity verification).
  2. Session Tokens: On bootstrap, when CU_SHIELD_GRPC_URL is set, the SDK creates a SessionTokenBackend instead of HmacBackend. This backend requests a session token from Shield, which is Ed25519-signed by Shield’s private key.
  3. Registration: The project sends RegisterManifest to the Router without a project_secret in the bundle. Instead, the Router fetches the project’s Ed25519 public key from Shield via GetProjectPublicKey().
  4. Verification: The Router verifies tokens using the project’s public key (cached in Redis). Key rotation is handled automatically — when a kid mismatch is detected, the Router re-fetches from Shield.

The Trust Model (Zero-Trust)

Because the project never possesses the signing key (Shield signs on its behalf), even a total compromise of the project process won’t leak the signing key. The Router can additionally enforce Shield policies (rate limits, permission boundaries) per project.


3. Transport Security (gRPC TLS)

Cryptographic token signing guarantees authenticity, but the data itself must be protected while traveling over the network. ContextUnity services communicate primarily via high-performance gRPC, which mandates encryption.

Standard TLS

By default, when GRPC_TLS_ENABLED=true, ContextUnity services enforce TLS server verification.

  • The server initializes using GRPC_TLS_SERVER_CERT and GRPC_TLS_SERVER_KEY.
  • The client connects using GRPC_TLS_CA_CERT to verify it’s talking to the legitimate Router/Brain.
  • The client does not prove its identity at the TCP level; its identity is proven strictly via the ContextToken interceptors.

This standard model protects against Man-in-the-Middle (MitM) attacks.

Mutual TLS (mTLS) — Zero-Trust (contextunity.shield)

For strict Zero-Trust deployments (like HIPAA compliance), contextunity.shield provides helpers for Mutual TLS (mTLS). In this mode, the client is additionally required to present a physical X.509 certificate to establish the TCP connection.

mTLS is enabled automatically when the client presents:

  • GRPC_TLS_CLIENT_CERT
  • GRPC_TLS_CLIENT_KEY

When both sides require mTLS, the Router refuses connection handshakes from any worker or client that lacks a valid certificate signed by the internal CA. Even if an attacker steals a perfectly valid, correctly signed ContextToken, their network request is dropped before it reaches the application layer, adding a powerful layer of defense-in-depth networking.


4. Application Secrets & Vault (contextunity.shield)

Beyond tokens and network encryption, applications (like Python agents in contextunity.router) frequently need API keys, database credentials, or third-party service tokens to perform their tasks.

Rather than injecting sensitive plaintext passwords directly into agents, contextunity.shield provides a dedicated gRPC Secrets API acting as a central Vault.

Access Control

To interact with the Secrets API, a service must present a ContextToken carrying specific permissions:

  • shield:secrets:read — required to read (GetSecret, ListSecrets, Decrypt)
  • shield:secrets:write — required to modify (PutSecret, RotateSecret)

Because tokens are securely signed (via KmsBackend or HmacBackend) and strictly scoped to a tenant_id, the Secrets API guarantees that Tenant A can never read Tenant B’s API keys.

How Shield Manages Secrets

contextunity.shield abstracts the physical storage of secrets through different backends:

  1. EnvSecretStore (Open-Source Default): Secrets are loaded securely into memory from environmental variables (e.g., SHIELD_SECRET_OPENAI_KEY). Good for basic setups.
  2. PgSecretStore / VaultSecretStore (Enterprise): Real-time, encrypted-at-rest vault solutions leveraging PostgreSQL or HashiCorp Vault.

Agent Workflow (Example)

When a contextunity.router Agent needs to call OpenAI:

  1. The Agent does not contain sk-proj-... in its code.
  2. Instead, the Agent makes a gRPC call to contextunity.shield asking for openai_api_key.
  3. Shield verifies the agent’s ContextToken, checks its tenant_id, and authenticates the read permission.
  4. Shield retrieves the secret from its active backend (e.g., HashiCorp Vault) and returns it over the mTLS encrypted channel.
  5. The Agent uses the key securely in memory and discards it after the execution cycle.

This ensures credentials remain centrally rotated, audited, and tightly segregated per project tenant.


5. Database-Level Isolation (PostgreSQL RLS)

Even if an attacker bypasses the Application Layer or a developer writes a vulnerable SQL tool (SQL Injection / Prompt Injection), ContextUnity enforces a final “Fail-Closed” layer of defense inside the database kernel.

contextunity.brain and contextunity.commerce utilize PostgreSQL Row-Level Security (RLS) to enforce strict Role-Based Access Control (RBAC) across two dimensions.

Dual-Dimensional RLS Policies

When a gRPC handler connects to the PostgreSQL pool, it passes the verified ContextToken. The database connection wrapper performs the following before executing any application query:

-- Inject token values into the physical DB session
SET LOCAL app.current_tenant = '{tenant_id}';
SET LOCAL app.current_user = '{user_id}';

All tables containing personal or project data (e.g., knowledge_nodes, episodic_events, user_facts) carry hardened RLS policies:

  1. Tenant Isolation (B2B):

    USING (tenant_id = current_setting('app.current_tenant', true))

    Guarantees that Project A can never SELECT or UPDATE rows belonging to Project B.

  2. User Isolation (B2C):

    USING (... AND (user_id IS NULL OR user_id = current_setting('app.current_user', true)))

    Guarantees that inside the same Tenant, User A can never see User B’s episodic memory or personal RAG vectors.

Role Enforcement

The application itself connects using the brain_app PostgreSQL role. This role does not have the BYPASSRLS privilege, meaning the PostgreSQL kernel rigidly enforces these policies on every query. The brain_admin role (used exclusively by the backend dashboard) is the only role capable of viewing cross-tenant metrics.