# Trigger Conditions Reference

This page provides a comprehensive reference for the SCIM filter syntax used in Lifecycle Management workflow trigger conditions. Trigger conditions determine **when** a workflow action should execute based on identity attributes.

## SCIM Filter Syntax Overview

SCIM (System for Cross-domain Identity Management) filter syntax provides a standardized way to express conditions. The basic structure is:

```txt
<attribute> <operator> <value>
```

For example:

```txt
department eq "Engineering"
```

This condition evaluates to `true` when the identity's `department` attribute equals "Engineering".

## Comparison Operators

### String Operators

| Operator | Name        | Description                      | Example                   |
| -------- | ----------- | -------------------------------- | ------------------------- |
| `eq`     | Equal       | Exact match (case-sensitive)     | `department eq "Sales"`   |
| `ne`     | Not Equal   | Does not match                   | `status ne "Terminated"`  |
| `co`     | Contains    | Substring match                  | `email co "@company.com"` |
| `sw`     | Starts With | Prefix match                     | `employee_id sw "EMP"`    |
| `ew`     | Ends With   | Suffix match                     | `email ew "@company.com"` |
| `pr`     | Present     | Attribute exists and is not null | `manager_id pr`           |

### Numeric Operators

| Operator | Name                  | Description                      | Example                  |
| -------- | --------------------- | -------------------------------- | ------------------------ |
| `eq`     | Equal                 | Exact numeric match              | `department_code eq 100` |
| `ne`     | Not Equal             | Does not equal                   | `level ne 0`             |
| `lt`     | Less Than             | Strictly less than               | `access_level lt 5`      |
| `le`     | Less Than or Equal    | Less than or equal to            | `risk_score le 50`       |
| `gt`     | Greater Than          | Strictly greater than            | `tenure_months gt 12`    |
| `ge`     | Greater Than or Equal | Greater than or equal to         | `salary_grade ge 3`      |
| `pr`     | Present               | Attribute exists and is not null | `access_level pr`        |

### Boolean Operators

| Operator | Name      | Description                      | Example                 |
| -------- | --------- | -------------------------------- | ----------------------- |
| `eq`     | Equal     | Boolean match                    | `is_active eq true`     |
| `ne`     | Not Equal | Boolean inverse                  | `is_contractor ne true` |
| `pr`     | Present   | Attribute exists and is not null | `is_contractor pr`      |

### Timestamp Operators

Timestamp comparisons use ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`).

| Operator | Name         | Description                      | Example                                      |
| -------- | ------------ | -------------------------------- | -------------------------------------------- |
| `eq`     | Equal        | Exact timestamp match            | `hire_date eq "2024-01-15T00:00:00Z"`        |
| `lt`     | Before       | Earlier than                     | `termination_date lt "2024-06-01T00:00:00Z"` |
| `le`     | At or Before | At or earlier than               | `start_date le "2024-12-31T23:59:59Z"`       |
| `gt`     | After        | Later than                       | `hire_date gt "2023-01-01T00:00:00Z"`        |
| `ge`     | At or After  | At or later than                 | `last_login ge "2024-01-01T00:00:00Z"`       |
| `pr`     | Present      | Attribute exists and is not null | `termination_date pr`                        |

### String List Operators

For attributes that contain multiple values (arrays), the following operators are supported:

| Operator | Name      | Description                       | Example                         |
| -------- | --------- | --------------------------------- | ------------------------------- |
| `co`     | Contains  | List contains a specific value    | `employee_types co "Full Time"` |
| `eq`     | Equal     | List exactly matches value(s)     | `roles eq "Admin"`              |
| `ne`     | Not Equal | List does not match value(s)      | `tags ne "deprecated"`          |
| `pr`     | Present   | Attribute exists and is not empty | `groups pr`                     |

{% hint style="info" %}
The `co` operator is most commonly used for checking membership in a list. Use `eq` for exact list matching and `pr` to verify the attribute has any values.
{% endhint %}

## Logical Operators

Combine multiple conditions using logical operators.

| Operator | Description                   | Example                                             |
| -------- | ----------------------------- | --------------------------------------------------- |
| `and`    | Both conditions must be true  | `is_active eq true and department eq "IT"`          |
| `or`     | Either condition must be true | `department eq "IT" or department eq "Engineering"` |
| `not`    | Negates a condition           | `not(status eq "Terminated")`                       |

{% hint style="info" %}
The `not()` operator uses parenthetical notation. For simple negation of a single value, prefer using `ne` (not equals) which has broader support across all condition contexts.
{% endhint %}

{% hint style="warning" %}
**Limitation:** The `not()` operator may not be fully supported in all LCM trigger condition contexts. If you encounter unexpected behavior with `not()`, rewrite the condition using `ne` or restructure the logic. For example, instead of `not(status eq "Active")`, use `status ne "Active"`.
{% endhint %}

### Precedence

* `not` has the highest precedence
* `and` has higher precedence than `or`
* Use parentheses `()` to control evaluation order

**Example combining operators:**

```txt
# Full-time employees in Engineering or IT departments
employee_types co "Full Time" and (department eq "Engineering" or department eq "IT")
```

## Common Trigger Condition Patterns

### Joiner Scenarios

```txt
# New full-time employees in specific departments
employee_types co "Full Time" and (department eq "Engineering" or department eq "Sales")

# New hires with specific job levels
is_active eq true and job_level ge 3 and hire_date gt "2024-01-01T00:00:00Z"

# Contractors starting in a specific region
is_contractor eq true and location sw "US-"
```

### Mover Scenarios

Two system attributes support mover detection:

* **`sys_attr__is_mover`**: Set to `true` when any property in the policy's **Mover Properties** list changes. Indicates that the identity changed, but does not identify which property changed.
* **`sys_attr_changed__<property>`**: Set to `true` for each specific property that changed in the most recent extraction. These attributes are transient and are cleared at the start of each extraction cycle.

Use `sys_attr__is_mover` when you want to trigger on any mover event. Use `sys_attr_changed__<property>` when you need to trigger only on specific property changes or combinations.

**Broad mover detection with `sys_attr__is_mover`**:

```txt
# Any change in monitored properties for active employees
sys_attr__is_mover eq true and is_active eq true

# Department-specific mover handling (identity moved AND is now in Engineering)
sys_attr__is_mover eq true and department eq "Engineering"

# Mover detection combined with employment type
sys_attr__is_mover eq true and is_active eq true and employee_types co "Full Time"
```

**Targeted mover detection with `sys_attr_changed__`**:

```txt
# Triggers only when department changes TO Sales (not when Sales employees change other attributes)
department_name eq "Sales" and sys_attr_changed__department_name eq true

# Triggers when manager changes for active employees in specific departments
sys_attr_changed__managers eq true and employment_status eq "ACTIVE" and (department_name eq "Engineering" or department_name eq "Marketing" or department_name eq "Sales")

# Triggers when any of several properties change
(sys_attr_changed__department_name eq true or sys_attr_changed__job_title eq true or sys_attr_changed__managers eq true) and employment_status eq "ACTIVE"

# Triggers only when BOTH a location field AND manager change in the same extraction
(sys_attr_changed__customprop_management_chain_level_03 eq true or sys_attr_changed__customprop_management_chain_level_04 eq true) and sys_attr_changed__managers eq true
```

See [System Attributes](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/transformers/system-attributes.md#sys_attr_changed__property) for the full `sys_attr_changed__` reference.

### Leaver Scenarios

```txt
# Terminated employees
employment_status eq "Terminated"

# Inactive contractors
is_active eq false and is_contractor eq true

# Users with imminent termination date
termination_date le "2024-12-31T23:59:59Z" and termination_date gt "2024-01-01T00:00:00Z"
```

### Attribute-Based Access Control

```txt
# High-privilege access for senior engineers
department eq "Engineering" and job_level ge 5 and is_active eq true

# Region-specific access
location sw "EMEA-" and employee_types co "Full Time"

# Cost center based provisioning
cost_center eq "CC-1000" and is_active eq true
```

## System Attributes in Conditions

Lifecycle Management provides two families of computed system attributes for use in trigger conditions:

* **`sys_attr__` prefix**: Persistent boolean flags such as `sys_attr__is_mover` (any monitored property changed) and `sys_attr__is_new_identity` (first appearance of an identity).
* **`sys_attr_changed__` prefix**: Per-property change detection attributes, transient per extraction cycle. `sys_attr_changed__department eq true` means department changed in the most recent extraction.

See [System Attributes](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/transformers/system-attributes.md) for the complete reference.

## Dynamic Value Comparisons with Embedded Transformers

For time-sensitive workflows, you can embed transformer functions directly in condition values. This enables comparisons against dynamically-computed dates and times rather than static values.

### Syntax

Embedded transformers use the `{| FUNCTION | ...}` syntax. The pipe (`|`) immediately after the opening brace indicates there is no source attribute—the expression starts directly with a function:

```txt
{| NOW | UTC_TO_TIME_ZONE, "-05:00" | DATE_FORMAT, "DateOnly"}
```

This differs from attribute transformers where you reference an attribute first:

* **Attribute transformer:** `{hire_date | DATE_FORMAT, "DateOnly"}` (starts with attribute)
* **Embedded in condition:** `{| NOW | DATE_FORMAT, "DateOnly"}` (starts with function)

### Common Functions for Dynamic Conditions

| Function           | Purpose                      | Example |
| ------------------ | ---------------------------- | ------- |
| `NOW`              | Current UTC timestamp        | \`{     |
| `UTC_TO_TIME_ZONE` | Convert to specific timezone | \`{     |
| `DATE_ADJUST_DAY`  | Add/subtract days            | \`{     |
| `DATE_FORMAT`      | Format for comparison        | \`{     |

See [Transformer Reference](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/transformers/transformer-reference.md) for all available functions.

### Example: 2-Day Leaver Window

Trigger a leaver workflow when an employee's last day of work falls within a 2-day window around today (Eastern Standard Time):

```txt
is_active eq true
and customprop_lastdayofwork le "{| NOW | UTC_TO_TIME_ZONE, \"-05:00\" | DATE_ADJUST_DAY, 0 | DATE_FORMAT, \"DateOnly\"}"
and customprop_lastdayofwork gt "{| NOW | UTC_TO_TIME_ZONE, \"-05:00\" | DATE_ADJUST_DAY, -2 | DATE_FORMAT, \"DateOnly\"}"
```

**Breaking down the embedded transformer:**

| Step | Function                     | Input              | Output                         |
| ---- | ---------------------------- | ------------------ | ------------------------------ |
| 1    | `NOW`                        | (none)             | Current UTC timestamp          |
| 2    | `UTC_TO_TIME_ZONE, "-05:00"` | UTC timestamp      | Eastern time timestamp         |
| 3    | `DATE_ADJUST_DAY, 0`         | EST timestamp      | Today (or `-2` for 2 days ago) |
| 4    | `DATE_FORMAT, "DateOnly"`    | Adjusted timestamp | Date string for comparison     |

**Result:** The workflow triggers when:

* The employee is active (`is_active eq true`)
* Their last day is today or earlier (`le` today)
* Their last day is after 2 days ago (`gt` 2 days ago)

This creates a 2-day processing window for departing employees.

### Example: Pre-Hire Provisioning

Trigger a joiner workflow 7 days before an employee's start date:

```txt
is_active eq false
and hire_date le "{| NOW | DATE_ADJUST_DAY, 7 | DATE_FORMAT, \"DateOnly\"}"
and hire_date gt "{| NOW | DATE_FORMAT, \"DateOnly\"}"
```

This triggers for employees whose hire date is within the next 7 days, enabling pre-provisioning of accounts before their start date.

### Example: Post-Termination Cleanup

Trigger a cleanup workflow for employees terminated more than 30 days ago:

```txt
employment_status eq "Terminated"
and termination_date lt "{| NOW | DATE_ADJUST_DAY, -30 | DATE_FORMAT, \"DateOnly\"}"
```

{% hint style="warning" %}
**Escaping quotes:** When embedding transformers in conditions, you must escape inner quotes with backslashes. For example: `\"-05:00\"` and `\"DateOnly\"`.
{% endhint %}

{% hint style="info" %}
**Timezone consideration:** Use `UTC_TO_TIME_ZONE` to ensure date comparisons align with your organization's business timezone. Without timezone conversion, comparisons use UTC which may cause workflows to trigger at unexpected times.
{% endhint %}

### Related Documentation

For a conceptual overview of how conditions and transformers work together, see [Understanding Conditions and Transformers](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/conditions-and-transformers-overview.md).

## Best Practices

### Use Specific Conditions

```txt
# Good: Specific and targeted
department eq "Engineering" and job_level ge 3 and is_active eq true

# Avoid: Too broad, may affect unintended users
department eq "Engineering"
```

### Test with Dry Run

Before enabling a policy, use the **Dry Run** feature to preview which identities match your trigger conditions. This helps catch overly broad or restrictive conditions before they affect real accounts.

### Combine Conditions Thoughtfully

```txt
# Use parentheses for clarity when mixing and/or
(department eq "IT" or department eq "Engineering") and is_active eq true

# Without parentheses, this evaluates differently due to precedence:
# department eq "IT" or (department eq "Engineering" and is_active eq true)
department eq "IT" or department eq "Engineering" and is_active eq true
```

### Handle Edge Cases

Consider what happens when attributes are null or empty:

```txt
# Explicit check for non-empty department
department ne "" and department eq "Engineering"

# Check for active status before other conditions
is_active eq true and department eq "Engineering"
```

## Troubleshooting

### Condition Not Matching Expected Users

1. **Check attribute names**: Ensure the attribute name exactly matches the source attribute (case-sensitive)
2. **Verify data types**: String values need quotes, booleans don't
3. **Review operator choice**: `co` for contains vs. `eq` for exact match
4. **Use Dry Run**: Test the condition against specific identities

### Condition Matching Too Many Users

1. **Add specificity**: Combine multiple conditions with `and`
2. **Check for broad patterns**: `co ""` matches all non-null values
3. **Verify logical grouping**: Ensure `and`/`or` precedence is correct

### Timestamp Issues

1. **Use ISO 8601 format**: `YYYY-MM-DDTHH:MM:SSZ`
2. **Include timezone**: Always use `Z` suffix for UTC
3. **Check attribute type**: Ensure the source attribute is a timestamp, not a string

## Related Topics

* [Understanding Conditions and Transformers](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/conditions-and-transformers-overview.md) - Conceptual overview of conditions vs. transformers
* [Policies](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/policies.md) - Create and configure Lifecycle Management policies
* [Conditions and Actions](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/actions.md) - Configure workflow actions and their triggers
* [Attribute Transformers](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/transformers.md) - Transform attribute values using formatter syntax
* [Transformer Reference](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/transformers/transformer-reference.md) - Complete list of transformation functions
* [System Attributes](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/transformers/system-attributes.md) - Available system attributes for conditions
* [Dynamic Access Profiles](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/profiles/dynamic-access-profiles.md) - Formatter-based profile assignment
* [Attribute Mapping](/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/transformers/attribute-mapping.md) - Map source attributes to target attributes


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.veza.com/4yItIzMvkpAvMVFAamTf/features/lifecycle-management/policies-workflows/actions/trigger-conditions-reference.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
