Instacart's JIT access playbook

CEL expressions reference

Complete reference for CEL expression objects, functions, and usage contexts in ConductorOne.

Functions

These library functions let you interact with the ConductorOne system to look up whether a user has access to a certain application or entitlement, or to find the user or list of users who should review a task.

User library functions

FunctionAcceptsReturnsAvailability
c1.user.v1.HasAppuser, app IDBooleanPolicies, Groups, Automations, Account provisioning
c1.user.v1.HasEntitlementuser, app ID, entitlement IDBooleanPolicies, Groups, Automations, Account provisioning
c1.user.v1.GrantedFromEnrollmentuser, app ID, entitlement IDBooleanPolicy conditions only
c1.user.v1.AutomaticallyGrantedFromEnrollmentuser, app ID, entitlement IDBooleanPolicy conditions only
c1.user.v1.ListAppUsersForUseruser, app IDList of AppUserAutomations, Account provisioning

Directory library functions

FunctionAcceptsReturnsAvailability
c1.directory.users.v1.FindByEmailemailuserPolicies, Groups, Automations, Account provisioning
c1.directory.users.v1.GetByIDuser IDuserPolicies, Groups, Automations, Account provisioning
c1.directory.users.v1.GetManagersuserlist of usersPolicies, Groups, Automations, Account provisioning
c1.directory.users.v1.DirectReportsuser or list of userslist of usersPolicies, Groups, Automations, Account provisioning
c1.directory.groups.v1.FindByNamegroup namegroupPolicies, Groups, Automations, Account provisioning
c1.directory.apps.v1.GetEntitlementMembersapp ID, entitlement IDlist of usersPolicies, Groups, Automations, Account provisioning

Go to an application or entitlement’s details page to look up its ID, or use Cone.

Function availability varies by context. Note that automation triggers do NOT have access to directory or user library functions - they can only access the ctx.trigger object and basic enums.

Time functions

ConductorOne provides comprehensive time functions for working with dates and times in CEL expressions. These functions are available in all CEL contexts (Policies, Groups, Automations, Account provisioning).

Core time functions

FunctionDescriptionExample
now()Get current timestampnow() > timestamp("2025-01-01T00:00:00Z")
time.parse(value, layout)Parse time from string (UTC)time.parse("2025-10-22", TimeFormat.DATE)
time.parse(value, layout, timezone)Parse time with timezonetime.parse("2025-10-22 14:30:00", TimeFormat.DATETIME, "America/New_York")
time.format(timestamp, layout)Format timestamp to string (UTC)time.format(now(), TimeFormat.RFC3339)
time.format(timestamp, layout, timezone)Format with timezonetime.format(now(), "Monday", "America/New_York")
time.unix(seconds)Convert Unix timestamp (seconds)time.unix(1734787200)
time.unix_ms(milliseconds)Convert Unix millisecondstime.unix_ms(1734787200123)
time.start_of(timestamp, unit)Get start of periodtime.start_of(now(), "day")
time.start_of(timestamp, unit, timezone)Get start of period in timezonetime.start_of(now(), "week", "America/New_York")
time.end_of(timestamp, unit)Get end of periodtime.end_of(now(), "month")

Time units for start_of/end_of:

  • "day" - Start/end of day (midnight)
  • "week" - Start/end of week (Monday/Sunday)
  • "month" - Start/end of month
  • "quarter" - Start/end of quarter (Jan/Apr/Jul/Oct)
  • "year" - Start/end of year

TimeFormat constants

ConstantFormatExample Output
TimeFormat.RFC3339ISO 8601 / RFC 33392025-10-22T14:30:00Z
TimeFormat.DATEDate only2025-10-22
TimeFormat.DATETIMEDate and time2025-10-22 14:30:00
TimeFormat.TIMETime only14:30:00

You can also use custom Go time layouts like "2006-01-02" or "Monday, January 2, 2006".

Common time patterns

Check if date is recent:

// Check if user's hire date is within last 30 days (if stored in profile)
has(subject.profile.hire_date) &&
time.parse(subject.profile.hire_date, TimeFormat.DATE) > now() - duration("720h")

// Account modified this month (in automations)
has(ctx.trigger.newAccount.updated_at) &&
timestamp(ctx.trigger.newAccount.updated_at) >= time.start_of(now(), "month")

Business hours checking:

// Check if it's business hours (9 AM - 5 PM ET)
time.format(now(), "15", "America/New_York") >= "09" &&
time.format(now(), "15", "America/New_York") < "17"

// Check if it's after hours
time.format(now(), "15", "America/New_York") >= "17" ||
time.format(now(), "15", "America/New_York") < "09"

Day of week checking:

// Check if it's a weekend
time.format(now(), "Monday", "America/New_York") == "Saturday" ||
time.format(now(), "Monday", "America/New_York") == "Sunday"

// Check if it's a weekday
!(time.format(now(), "Monday") == "Saturday" || time.format(now(), "Monday") == "Sunday")

Parsing profile date fields:

// Parse contract end date and check if within 30 days
has(subject.profile.contract_end_date) &&
time.parse(subject.profile.contract_end_date, TimeFormat.DATE) - now() < duration("720h")

// Check if hire date is in the past
has(subject.profile.hire_date) &&
time.parse(subject.profile.hire_date, TimeFormat.DATE) < now()

Working with timezones:

// Start of day in company timezone
time.start_of(now(), "day", "America/New_York")

// Format date in user's timezone
time.format(now(), TimeFormat.DATETIME, "Europe/London")

Important: The now() function returns the same value throughout a single expression evaluation. All timestamps are stored in UTC internally; timezone parameters only affect parsing and formatting.

Objects

Subject object

The “subject” variable refers to the ConductorOne user.

Most common fields

These fields are used in the majority of condition expressions:

FieldData typeDescriptionExample usageCommon use cases
subject.emailstringUser’s email addresssubject.email.endsWith("@company.com")Distinguish between employees and contractors
subject.departmentstringUser’s departmentsubject.department == "Engineering"Department-based access control
subject.statusenumUser’s active statussubject.status == UserStatus.ENABLEDCheck if user is active
subject.typeenumUser type (human, service, system)subject.type == UserType.HUMANFilter by user type

Identity and contact fields

FieldData typeDescriptionExample usageCommon use cases
subject.idstringUnique user identifiersubject.id == "user123"Specific user targeting
subject.email.startsWithstringEmail prefix checksubject.email.startsWith("admin")Admin user identification
subject.email.endsWithstringEmail domain checksubject.email.endsWith("@company.com")Employee vs contractor
subject.managerstringUser’s manager emailsubject.manager == "boss@company.com"Manager-based routing

Organizational fields

FieldData typeDescriptionExample usageCommon use cases
subject.jobTitlestringUser’s job titlesubject.jobTitle == "Senior Developer"Role-based access
subject.employmentTypestringEmployment typesubject.employmentType == "Full Time"Employment status checks
subject.employmentStatusstringEmployment statussubject.employmentStatus == "Active"Active employee verification

Status and directory fields

FieldData typeDescriptionExample usageCommon use cases
subject.directoryStatusenumDirectory sync statussubject.directoryStatus == UserStatus.ENABLEDDirectory health checks
subject.profilemap[string]interface{}Profile attributessubject.profile.department == "IT"Custom profile data access
subject.attributes.<CUSTOM_USER_ATTRIBUTE>variesCustom user attributessubject.attributes.contractor == "true"Custom business logic

Enum values reference

UserStatus values:

  • UserStatus.ENABLED - User is active
  • UserStatus.DISABLED - User is disabled
  • UserStatus.DELETED - User is deleted

UserType values:

  • UserType.HUMAN - Regular human user
  • UserType.AGENT - Automated agent
  • UserType.SERVICE - Service account
  • UserType.SYSTEM - System account

Use custom user attributes. You can write condition expressions that leverage the custom user attributes you’ve set up in ConductorOne. Any custom user attribute can be passed in to the subject.attributes.<CUSTOM USER ATTRIBUTE> property and used in your condition expressions.

User object

The user object is used when referencing other users in the system (not the current subject).

FieldData typeDescriptionExample usageCommon use cases
user.idstringUnique user identifieruser.id == "user123"Specific user targeting
user.emailstringUser’s email addressuser.email.endsWith("@company.com")Email-based filtering
user.displayNamestringUser’s display nameuser.displayName == "John Doe"Name-based identification
user.usernamestringUser’s usernameuser.username == "johndoe"Username-based filtering
user.departmentstringUser’s departmentuser.department == "Engineering"Department-based grouping
user.jobTitlestringUser’s job titleuser.jobTitle == "Manager"Role-based filtering
user.statusUserStatus enumUser’s active statususer.status == UserStatus.ENABLEDActive user verification
user.directoryStatusUserStatus enumDirectory sync statususer.directoryStatus == UserStatus.ENABLEDDirectory health checks
user.employmentTypestringEmployment typeuser.employmentType == "Full Time"Employment status filtering
user.employmentStatusstringEmployment statususer.employmentStatus == "Active"Active employee verification
user.profileJSONProfile attributesuser.profile.department == "IT"Custom profile data access

Task object

The task object is used in policy expressions to reference the current access request or task.

FieldData typeDescriptionExample usageCommon use cases
task.idstringUnique task identifiertask.id == "task123"Specific task targeting
task.numericIdstringNumeric task identifiertask.numericId == "12345"Numeric task reference
task.displayNamestringHuman-readable task nametask.displayName == "Access Request"Task identification
task.originTaskOrigin enumWhere the task was createdtask.origin == TaskOrigin.SLACKRoute based on creation source
task.isGrantPermanentBooleanWhether access is permanenttask.isGrantPermanent == truePermanent vs temporary access
task.grantDurationdurationHow long access is grantedtask.grantDuration > duration("2h")Time-based access control
task.analysisanalysisTask analysis datatask.analysis.hasConflictViolationsAccess conflict detection

TaskOrigin values:

  • TaskOrigin.WEBAPP - Created in ConductorOne web interface
  • TaskOrigin.SLACK - Created via Slack integration
  • TaskOrigin.API - Created via API
  • TaskOrigin.JIRA - Created via Jira integration
  • TaskOrigin.COPILOT - Created via Copilot
  • TaskOrigin.PROFILE_MEMBERSHIP_AUTOMATION - Created by automation
  • TaskOrigin.TIME_REVOKE - Created by time-based revocation

Task analysis object

The task analysis object provides information about potential access conflicts and other analysis data.

FieldData typeDescriptionExample usageCommon use cases
task.analysis.idstringAnalysis identifiertask.analysis.id == "analysis123"Specific analysis reference
task.analysis.hasConflictViolationsBooleanWhether conflicts existtask.analysis.hasConflictViolationsCheck for access conflicts
task.analysis.conflictViolationsarray of stringsList of conflict IDs"conflict123" in task.analysis.conflictViolationsSpecific conflict detection

Entitlement object

The entitlement object can only be used in CEL expressions in policies. It does not work when writing CEL expressions to form ConductorOne groups.

FieldData typeDescriptionExample usageCommon use cases
entitlement.idstringEntitlement identifierentitlement.id == "entitlement123"Specific entitlement reference
entitlement.appIdstringApplication identifierentitlement.appId == "app123"Application-specific logic

IP address object

The IP address object is used for network-based access control and filtering.

FieldData typeDescriptionExample usageCommon use cases
ip.is4BooleanWhether IP is IPv4ip.is4IPv4-specific logic
ip.is6BooleanWhether IP is IPv6ip.is6IPv6-specific logic
ip.isPrivateBooleanWhether IP is privateip.isPrivateInternal network access
ip.isLoopbackBooleanWhether IP is loopbackip.isLoopbackLocalhost detection
ip.isGlobalUnicastBooleanWhether IP is global unicastip.isGlobalUnicastPublic IP detection
ip.isMulticastBooleanWhether IP is multicastip.isMulticastMulticast traffic detection
ip.isInterfaceLocalMulticastBooleanWhether IP is interface local multicastip.isInterfaceLocalMulticastLocal multicast detection
ip.isLinkLocalMulticastBooleanWhether IP is link local multicastip.isLinkLocalMulticastLink local multicast detection
ip.isUnspecifiedBooleanWhether IP is unspecifiedip.isUnspecifiedInvalid IP detection

IP CIDR object

The IP CIDR object is used for network range-based access control and filtering.

FunctionDescriptionExample usageCommon use cases
cidr('10.1.2.0/24').contains(ip('1.2.3.4'))Check if IP is within CIDR rangecidr('10.1.2.0/24').contains(ip('10.1.2.5'))Network-based access control
ip('10.1.2.5').within(cidr('10.1.2.0/24'))Check if IP is within CIDR rangeip('10.1.2.5').within(cidr('10.1.2.0/24'))Alternative syntax for range checking
cidr('10.1.2.0/24', '5.4.3.2/32')Create CIDR range with multiple networkscidr('10.1.2.0/24', '5.4.3.2/32')Multiple network range definition

Object usage reference

Understanding where each object can be used helps you write effective CEL expressions for different ConductorOne features.

Quick object reference table

ObjectPoliciesGroupsAutomationsCampaignsAccount provisioning
subject✅*
user✅*⛔️
task⛔️⛔️⛔️⛔️
task.analysis⛔️⛔️⛔️⛔️
entitlement⛔️⛔️⛔️⛔️
ctx⛔️⛔️⛔️⛔️
ip⛔️⛔️⛔️
ip CIDR⛔️⛔️⛔️

* In Automations, user data is accessed through the ctx object (e.g., ctx.trigger.newUser, ctx.trigger.oldUser)

Subject object

Available in: ✅ Policies ✅ Groups ✅ Automations ✅ Campaigns ✅ Account provisioning
Description: References the current user in the context
Usage: The most commonly used object across all CEL expression contexts

Context-specific examples:

In Policies:

// Policy conditional - check if user is in Engineering department
subject.department == "Engineering"

// Policy expression - route to user's manager
c1.directory.users.v1.FindByEmail(subject.manager)

In Groups:

// Group membership - include all Engineering employees
subject.department == "Engineering" && subject.status == UserStatus.ENABLED

In Automations:

// Automation trigger - when user status changes
subject.status == UserStatus.DISABLED

In Campaigns:

// User selection - include contractors only
!subject.email.endsWith("@company.com")

In Account provisioning:

// Data mapping - use user's first name
subject.attributes.firstName

User object

Available in: ✅ Policies ✅ Groups ✅ Automations ✅ Campaigns ⛔️ Account provisioning
Description: References other users in the system (not the current subject)
Usage: Used when you need to reference or compare against other users

Context-specific examples:

In Policies:

// Policy expression - assign to specific user
c1.directory.users.v1.GetByID("user123")

In Groups:

// Group membership - include users by department
user.department == "Engineering"

In Automations:

// Automation step - modify specific user
user.status == UserStatus.DISABLED

In Campaigns:

// User selection - include users by status
user.status == UserStatus.ENABLED

Task object

Available in: ✅ Policies ⛔️ Groups ⛔️ Automations ⛔️ Campaigns ⛔️ Account provisioning
Description: References the current access request or task
Usage: Only available in policy expressions where there’s an active task context

Context-specific examples:

In Policies:

// Policy conditional - check task origin
task.origin == TaskOrigin.SLACK

// Policy conditional - check for access conflicts
task.analysis.hasConflictViolations

// Policy conditional - time-based access
task.isGrantPermanent == false && task.grantDuration > duration("2h")

Task analysis object

Available in: ✅ Policies ⛔️ Groups ⛔️ Automations ⛔️ Campaigns ⛔️ Account provisioning
Description: Provides information about potential access conflicts and other analysis data
Usage: Only available in policy expressions for conflict detection and analysis

Context-specific examples:

In Policies:

// Policy conditional - check for any conflicts
task.analysis.hasConflictViolations

// Policy conditional - check for specific conflict
"conflict123" in task.analysis.conflictViolations

Entitlement object

Available in: ✅ Policies ⛔️ Groups ⛔️ Automations ⛔️ Campaigns ⛔️ Account provisioning
Description: References the entitlement being requested
Usage: Only available in policy expressions where there’s an active entitlement request

Context-specific examples:

In Policies:

// Policy conditional - check specific entitlement
entitlement.id == "entitlement123"

// Policy expression - assign to users with same entitlement
c1.directory.apps.v1.GetEntitlementMembers(entitlement.appId, entitlement.id)

IP address object

Available in: ✅ Policies ⛔️ Groups ✅ Automations ⛔️ Campaigns ⛔️ Account provisioning
Description: Used for network-based access control and filtering
Usage: Available in policies and automations for network-based logic

Context-specific examples:

In Policies:

// Policy conditional - check if IP is private
ip.isPrivate

// Policy conditional - check if IP is IPv4
ip.is4

In Automations:

// Automation trigger - when IP is from private network
ip.isPrivate

IP CIDR object

Available in: ✅ Policies ⛔️ Groups ✅ Automations ⛔️ Campaigns ⛔️ Account provisioning
Description: Used for network range-based access control and filtering
Usage: Available in policies and automations for network range checking

Context-specific examples:

In Policies:

// Policy conditional - check if IP is in range
cidr('10.1.2.0/24').contains(ip('10.1.2.5'))

In Automations:

// Automation trigger - when IP is in specific range
ip('10.1.2.5').within(cidr('10.1.2.0/24'))

Context object (ctx)

Available in: ⛔️ Policies ⛔️ Groups ✅ Automation Triggers ✅ Workflow Steps ⛔️ Campaigns ⛔️ Account provisioning
Description: Provides access to workflow execution context and trigger data
Usage: Used in automations to access trigger data and previous step outputs

Available fields:

In Automation Triggers:

  • ctx.trigger.oldUser / ctx.trigger.old_user - User state before change
  • ctx.trigger.newUser / ctx.trigger.new_user - User state after change
  • ctx.trigger.oldAccount / ctx.trigger.old_account - Account state before change
  • ctx.trigger.newAccount / ctx.trigger.new_account - Account state after change
  • ctx.trigger.entitlement - Entitlement that triggered the workflow

In Workflow Steps:

  • ctx.trigger - Trigger output data (structure varies by trigger type)
  • ctx.[step_name] - Output from each completed workflow step

Context-specific examples:

In automation triggers:

// Trigger when user changes departments
ctx.trigger.newUser.department != ctx.trigger.oldUser.department && 
ctx.trigger.newUser.department == "Engineering"

// Trigger when account status changes to disabled
ctx.trigger.newAccount.status.status == APP_USER_STATUS_DISABLED &&
ctx.trigger.oldAccount.status.status == APP_USER_STATUS_ENABLED

In automation steps:

// Access trigger data
ctx.trigger.user.email

// Template syntax for embedding in strings
"User {{ ctx.trigger.user.display_name }} changed departments"

Important: Automation triggers have limited function access. They do NOT have access to directory functions (c1.directory.*) or user entitlement checking functions (c1.user.v1.HasApp, etc.). Only basic user/account field access and status enums are available.

Important notes

Use camelCase

CEL expressions should be written in camelCase. ConductorOne is moving away from snake_case for consistency and readability. Existing expressions in snake_case will still work, but new ones should follow the camelCase convention.

Null safety with has()

Use the has() macro to check for existence of optional fields, especially in profile maps:

has(subject.profile.custom_field) ? subject.profile.custom_field == "value" : false

Performance considerations

Directory functions (c1.directory.*) perform I/O operations. Place them after simpler conditions when possible:

// Good: Check fast conditions first
subject.department == "Engineering" && c1.directory.users.v1.FindByEmail(subject.email)

// Less optimal: I/O operation runs for all evaluations
c1.directory.users.v1.FindByEmail(subject.email) && subject.department == "Engineering"

Function memoization

Directory function calls are automatically memoized within a single expression evaluation, so calling the same function multiple times is safe and efficient.

Template syntax

Only Workflow Steps support {{ expression }} template syntax for embedding CEL expressions in strings.