{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "sailpoint.isc.transforms.dateCompare.schema.json",
  "title": "SailPoint ISC Transform Schema - dateCompare",
  "description": "Strict schema for the SailPoint ISC Date Compare transform. Compares firstDate against secondDate using the specified operator and returns positiveCondition (true) or negativeCondition (false). Both date operands must be ISO8601 datetime strings, the keyword 'now', or nested transforms whose output is ISO8601.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "type",
    "name",
    "attributes"
  ],
  "properties": {
    "type": {
      "const": "dateCompare",
      "description": "Transform operation type. Must be exactly 'dateCompare'."
    },
    "name": {
      "type": "string",
      "minLength": 1,
      "description": "Display name for this transform, shown in UI dropdowns and identity profile mappings."
    },
    "requiresPeriodicRefresh": {
      "type": "boolean",
      "default": false,
      "description": "If true, re-evaluates this transform during the nightly identity refresh cycle. RECOMMENDED when either date operand uses 'now', so time-based comparisons stay current. Default is false."
    },
    "attributes": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "firstDate",
        "secondDate",
        "operator",
        "positiveCondition",
        "negativeCondition"
      ],
      "properties": {
        "firstDate": {
          "$ref": "#/$defs/DateOperand",
          "description": "Left-hand side of the comparison. Must be an ISO8601 datetime string (with time and timezone), the keyword 'now', or a nested transform whose output is ISO8601."
        },
        "secondDate": {
          "$ref": "#/$defs/DateOperand",
          "description": "Right-hand side of the comparison. Must be an ISO8601 datetime string (with time and timezone), the keyword 'now', or a nested transform whose output is ISO8601."
        },
        "operator": {
          "type": "string",
          "description": "Comparison operator (SailPoint docs specify uppercase). LT = firstDate < secondDate, LTE = firstDate ≤ secondDate, GT = firstDate > secondDate, GTE = firstDate ≥ secondDate. Case-insensitive at runtime but uppercase is recommended.",
          "enum": ["LT", "LTE", "GT", "GTE", "lt", "lte", "gt", "gte"]
        },
        "positiveCondition": {
          "type": "string",
          "description": "String value returned when the comparison evaluates to true. Can be any string (e.g., 'active', 'true', 'legacy'). Cannot be null."
        },
        "negativeCondition": {
          "type": "string",
          "description": "String value returned when the comparison evaluates to false. Can be any string (e.g., 'inactive', 'false', 'regular'). Cannot be null."
        }
      }
    }
  },
  "$defs": {
    "DateOperand": {
      "description": "A date operand: the keyword 'now' (evaluated at runtime), a full ISO8601 datetime string (must include time and timezone), or a nested transform object whose output is an ISO8601 datetime string.",
      "oneOf": [
        {
          "type": "string",
          "const": "now",
          "description": "The special keyword 'now', evaluated to the current datetime at transform execution. Must be lowercase."
        },
        {
          "type": "string",
          "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,9})?)?(Z|[+-]\\d{2}:\\d{2})$",
          "description": "ISO8601 datetime string with time and timezone. Examples: '2025-01-15T00:00:00Z', '1995-12-31T00:00:00-05:00'."
        },
        {
          "$ref": "#/$defs/NestedTransform"
        }
      ]
    },
    "NestedTransform": {
      "type": "object",
      "description": "A nested transform object that produces a date value. The output must be an ISO8601 datetime string. Use a dateFormat transform with outputFormat: 'ISO8601' if the source attribute is not already in ISO8601 format. The 'name' field is optional in nested transforms per SailPoint docs.",
      "additionalProperties": false,
      "required": [
        "type",
        "attributes"
      ],
      "properties": {
        "id": {
          "type": "string",
          "description": "Optional ID when referencing an existing saved transform."
        },
        "name": {
          "type": "string",
          "minLength": 1,
          "description": "Optional display name for the nested transform."
        },
        "type": {
          "type": "string",
          "minLength": 1,
          "description": "The operation type of the nested transform (e.g., 'accountAttribute', 'dateFormat', 'dateMath')."
        },
        "requiresPeriodicRefresh": {
          "type": "boolean",
          "description": "Whether this nested transform re-evaluates during nightly refresh."
        },
        "attributes": {
          "type": "object",
          "additionalProperties": true,
          "description": "Operation-specific attributes for the nested transform."
        }
      }
    }
  },
  "examples": [
    {
      "name": "Is Termination Date in the Future",
      "type": "dateCompare",
      "requiresPeriodicRefresh": true,
      "attributes": {
        "firstDate": {
          "type": "accountAttribute",
          "attributes": {
            "sourceName": "HR Source",
            "attributeName": "termination_date"
          }
        },
        "secondDate": "now",
        "operator": "GT",
        "positiveCondition": "active",
        "negativeCondition": "terminated"
      }
    },
    {
      "name": "Legacy vs Regular Employee Cutover",
      "type": "dateCompare",
      "attributes": {
        "firstDate": {
          "type": "accountAttribute",
          "attributes": {
            "sourceName": "HR Source",
            "attributeName": "hire_date"
          }
        },
        "secondDate": {
          "type": "dateFormat",
          "attributes": {
            "input": "12/31/1995",
            "inputFormat": "M/d/yyyy",
            "outputFormat": "ISO8601"
          }
        },
        "operator": "LTE",
        "positiveCondition": "legacy",
        "negativeCondition": "regular"
      }
    },
    {
      "name": "Hire Date Before Cutover Check",
      "type": "dateCompare",
      "requiresPeriodicRefresh": false,
      "attributes": {
        "firstDate": "2020-01-01T00:00:00Z",
        "secondDate": {
          "type": "accountAttribute",
          "attributes": {
            "applicationName": "corp-hr-system",
            "attributeName": "HIREDATE"
          }
        },
        "operator": "LT",
        "positiveCondition": "pre-2020",
        "negativeCondition": "post-2020"
      }
    }
  ]
}
