Skip to content

ContextToken Security

ContextToken is the authorization mechanism for the entire ContextUnity ecosystem. It implements a capability-based security model where each token carries specific permissions, tenant scoping, and identity information.

Token Structure

ContextToken is a frozen dataclass:

from contextcore.tokens import ContextToken
@dataclass(frozen=True)
class ContextToken:
token_id: str # Unique identifier for audit trails
permissions: tuple[str, ...] = () # Capabilities (e.g., "catalog:read")
allowed_tenants: tuple[str, ...] = () # Tenant IDs (empty = admin/all)
exp_unix: float | None = None # Expiration timestamp
revocation_id: str | None = None # For instant revocation
user_id: str | None = None # Human user identity
agent_id: str | None = None # Executing agent identity
user_namespace: str = "default" # Access tier: free, pro, admin, system

Creating Tokens

Tokens are created via TokenBuilder.mint_root():

from contextcore.tokens import TokenBuilder
builder = TokenBuilder(enabled=True, private_key_path="/path/to/key")
token = builder.mint_root(
user_ctx={},
permissions=["brain:read", "brain:write", "router:dispatch"],
ttl_s=3600,
allowed_tenants=["my_project"],
user_id="user_123",
agent_id="rag-agent",
user_namespace="pro",
)

Token Validation

# Check specific permission
token.has_permission("brain:read") # True
# Check tenant access
token.can_access_tenant("my_project") # True
token.can_access_tenant("other") # False
# Check expiration
token.is_expired() # False (if TTL hasn't elapsed)
# Check against ContextUnit security scopes
token.can_read(unit.security) # Checks read scopes
token.can_write(unit.security) # Checks write scopes

Token Attenuation (Delegation)

Child tokens can only have fewer permissions than the parent:

child_token = builder.attenuate(
token,
permissions=["brain:read"], # Subset of parent's permissions
ttl_s=600, # Shorter TTL
agent_id="tool-agent", # New agent identity
)
# user_id, user_namespace, allowed_tenants are inherited and CANNOT be expanded

Permission Model

Permissions follow the service:action or domain:action format:

PermissionDescription
brain:readQuery knowledge, memory, taxonomy
brain:writeUpsert knowledge, add episodes
catalog:readRead product catalog
product:writeModify product data
router:dispatchSend requests to Router
data:readDefault read permission
data:writeDefault write permission

Three-Layer Security Model

ContextUnity enforces security at three independent layers:

concepts-contexttoken

Layer 1 — Token Validation Interceptor

Every gRPC call must include a valid token in metadata. The interceptor:

  • Extracts the token from gRPC metadata
  • Verifies the cryptographic signature (Ed25519 or KMS via ContextShield)
  • Checks is_expired()
  • Rejects unsigned/expired/malformed tokens

Layer 2 — Permission Check

Each service validates permissions per RPC method:

  • has_permission("brain:read") for QueryMemory
  • can_access_tenant(tenant_id) for tenant scoping
  • can_read(unit.security) / can_write(unit.security) for ContextUnit access

Layer 3 — Database Row-Level Security

PostgreSQL RLS ensures data isolation even if application logic is bypassed.

Multi-Tenant Isolation

# Token scoped to specific tenants
token = builder.mint_root(
user_ctx={},
permissions=["brain:read"],
ttl_s=3600,
allowed_tenants=["project_alpha", "project_beta"],
)
token.can_access_tenant("project_alpha") # ✅ True
token.can_access_tenant("project_gamma") # ❌ False
# Admin token (empty allowed_tenants = access all)
admin_token = builder.mint_root(
user_ctx={},
permissions=["brain:read"],
ttl_s=3600,
allowed_tenants=[], # Admin — unrestricted
)
admin_token.can_access_tenant("any_tenant") # ✅ True

Signing Backends

BackendUse CaseConfiguration
Ed25519Production, self-hostedSIGNING_BACKEND=ed25519, key file paths
Cloud KMSEnterprise (via ContextShield)SIGNING_BACKEND=kms, KMS_KEY_RESOURCE
DisabledTesting onlySECURITY_ENABLED=false