Lucid Cedar Schema Reference
This document defines the complete Cedar schema used by Lucid for policy evaluation. The schema describes all entity types, actions, and the ClaimsContext structure available in Cedar policies.
Schema Overview
The Lucid Cedar schema defines how principals, actions, resources, and context map to the AI verification domain.
namespace Lucid {
entity User in [Group, Organization];
entity Agent in [Workspace, Organization];
entity APIKey in [Workspace];
entity Group in [Organization];
entity Workspace in [Organization];
entity Organization;
entity Service;
action "invoke" appliesTo {
principal: [User, Agent, APIKey],
resource: [Agent],
context: ClaimsContext
};
action "access_data" appliesTo {
principal: [User, Agent],
resource: [Service, Agent],
context: ClaimsContext
};
}
Entity Types
User
Represents a human user making a request.
| Attribute | Type | Description |
|---|---|---|
id |
String |
User identifier |
email |
String |
User email |
groups |
Set<Group> |
Groups the user belongs to |
org |
Organization |
User's organization |
Agent
Represents an AI agent being invoked or making requests.
| Attribute | Type | Description |
|---|---|---|
id |
String |
Agent identifier |
name |
String |
Agent display name |
workspace |
Workspace |
Workspace the agent belongs to |
org |
Organization |
Agent's organization |
spiffe_id |
String |
SPIFFE workload identity |
pii_authorized |
Boolean |
Whether agent is authorized for PII access |
allowed_regions |
Set<String> |
Allowed processing regions |
has_pii_access |
Boolean |
PII access flag |
model_id |
String |
Model the agent uses |
deployment_type |
String |
full, model, app, or bridge |
APIKey
Represents an API key used for programmatic access.
| Attribute | Type | Description |
|---|---|---|
id |
String |
Key identifier |
purpose |
String |
Key purpose (e.g., cli, webhook, agent) |
workspace |
Workspace |
Workspace the key belongs to |
Group
Represents a user group for role-based policies.
| Attribute | Type | Description |
|---|---|---|
id |
String |
Group identifier |
name |
String |
Group name |
Workspace
Represents a workspace containing multiple agents.
| Attribute | Type | Description |
|---|---|---|
id |
String |
Workspace identifier |
name |
String |
Workspace name |
org |
Organization |
Parent organization |
Organization
Represents the top-level organization.
| Attribute | Type | Description |
|---|---|---|
id |
String |
Organization identifier |
name |
String |
Organization name |
Service
Represents an external service that agents can access.
| Attribute | Type | Description |
|---|---|---|
id |
String |
Service identifier |
service |
String |
Service name (e.g., slack, github, compliance-api) |
Actions
invoke
The primary action for calling an AI agent. Used for request/response policy evaluation.
// Applies to:
// principal: User, Agent, or APIKey
// resource: Agent
// context: ClaimsContext
forbid(principal, action == Action::"invoke", resource)
when { context.claims.toxic_content > 0.8 };
access_data
Action for agent data access requests (OBO delegation, external service access).
// Applies to:
// principal: User or Agent
// resource: Service or Agent
// context: ClaimsContext
permit(principal, action == Action::"access_data", resource)
when {
principal.spiffe_id == "spiffe://lucid.ai/agent/legal-bot" &&
resource.service == "compliance-api"
};
ClaimsContext
The ClaimsContext is the primary structure available in Cedar when/unless clauses. It contains all claims collected from ClaimsAuditors plus request metadata.
Structure
type ClaimsContext = {
// Request metadata
phase: String, // "request", "response", "artifact", "execution"
trace_id: String, // Distributed trace identifier
session_id?: String, // Session identifier
model_id?: String, // Model being invoked
// Collected claims (from all auditors)
claims: ClaimsMap,
// OBO delegation context (when agent acts on behalf of user)
act?: ActorContext
};
ClaimsMap
All auditor claims are available under context.claims. Claim names are flat descriptive identifiers that map directly to Cedar context paths:
| Claim Name | Cedar Context Path |
|---|---|
toxic_content |
context.claims.toxic_content |
injection_risk |
context.claims.injection_risk |
pii_types |
context.claims.pii_types |
pii_count |
context.claims.pii_count |
pii_risk_score |
context.claims.pii_risk_score |
redaction_applied |
context.claims.redaction_applied |
detected_regions |
context.claims.detected_regions |
location_confidence |
context.claims.location_confidence |
required_benchmarks_complete |
context.claims.required_benchmarks_complete |
faithfulness |
context.claims.faithfulness |
hallucination_score |
context.claims.hallucination_score |
answer_relevancy |
context.claims.answer_relevancy |
demographic_parity_diff |
context.claims.demographic_parity_diff |
latency_ms |
context.claims.latency_ms |
token_count |
context.claims.token_count |
cost_usd |
context.claims.cost_usd |
safety_score |
context.claims.safety_score |
watermark_applied |
context.claims.watermark_applied |
watermark_confidence |
context.claims.watermark_confidence |
watermark_detected |
context.claims.watermark_detected |
secret_leaked |
context.claims.secret_leaked |
artifact.hash_valid |
context.claims.artifact_hash_valid |
Claim Type Mapping to Cedar Types
| Claim Type | Cedar Type | Cedar Operations |
|---|---|---|
score_normalized |
Long (scaled to 0-1000) |
>, <, >=, <=, == |
boolean |
Bool |
==, != |
string |
String |
==, !=, like |
string_list |
Set<String> |
contains, containsAll, containsAny |
count |
Long |
>, <, >=, <=, == |
duration_ms |
Long |
>, <, >=, <=, == |
Score Normalization
Cedar uses integer arithmetic. Normalized scores (0.0-1.0) are scaled to 0-1000 in the ClaimsContext. A toxicity score of 0.8 becomes 800 in Cedar. For readability, Cedar policies use decimal notation (context.claims.toxic_content > 0.8) and the Gateway handles the conversion.
ActorContext (OBO Delegation)
When an agent acts on behalf of a user, the act context is populated:
type ActorContext = {
sub: String, // SPIFFE ID of the acting agent
iss: String, // Token issuer
scope: Set<String> // Delegated scopes
};
// Agent can only access Slack on behalf of engineering team members
permit(principal, action == Action::"access_data", resource)
when {
context.act.sub == "spiffe://lucid.ai/agent/slack-assistant" &&
resource.service == "slack" &&
principal in Group::"engineering"
};
Policy Annotations
Lucid extends Cedar with custom annotations for policy management:
| Annotation | Values | Description |
|---|---|---|
scope |
org, workspace, agent |
Policy scope level |
id |
Any string | Unique policy rule identifier |
workspace_id |
Workspace ID | Target workspace (for workspace-scoped policies) |
agent_id |
Agent ID | Target agent (for agent-scoped policies) |
decision |
deny, warn, escalate, shadow, log |
How to handle the decision |
compliance_framework |
Framework name | Regulatory framework mapping |
control_id |
Control identifier | Specific regulatory control |
description |
Free text | Human-readable description |
Annotation Examples
@annotation("scope", "org")
@annotation("id", "org-injection-block")
@annotation("compliance_framework", "NIST AI")
@annotation("control_id", "MEASURE 2.7")
@annotation("description", "Block all prompt injection attempts org-wide")
forbid(principal, action == Action::"invoke", resource)
when { context.claims.injection_risk > 0.7 };
Full Example Policy
// ============================================
// Organization Baseline (cannot be overridden)
// ============================================
@annotation("scope", "org")
@annotation("id", "org-injection")
forbid(principal, action == Action::"invoke", resource)
when {
context.claims.injection_risk > 0.7
};
@annotation("scope", "org")
@annotation("id", "org-secrets")
forbid(principal, action == Action::"invoke", resource)
when { context.claims.secret_leaked == true };
// ============================================
// Workspace: Customer Support (stricter rules)
// ============================================
@annotation("scope", "workspace")
@annotation("workspace_id", "ws-customer-support")
@annotation("id", "ws-toxicity")
forbid(principal, action == Action::"invoke", resource)
when { context.claims.toxic_content > 0.3 };
@annotation("scope", "workspace")
@annotation("workspace_id", "ws-customer-support")
@annotation("id", "ws-pii-escalate")
@annotation("decision", "escalate")
forbid(principal, action == Action::"invoke", resource)
when { context.claims.pii_count > 3 };
// ============================================
// Agent: Legal Reviewer (requires location)
// ============================================
@annotation("scope", "agent")
@annotation("agent_id", "agent-legal-reviewer")
@annotation("id", "agent-location")
forbid(principal, action == Action::"invoke", resource)
when { context.claims.location_confidence < 0.5 };
// ============================================
// Default permit (everything not forbidden)
// ============================================
permit(principal, action == Action::"invoke", resource);