Skip to content

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);