array

Array manipulation functions.

Array Functions

Array operations for building authorization policies that work with collections of values. Test membership, combine sets of permissions, aggregate numeric data, and transform attribute lists.

Core Principles

Array functions treat inputs as immutable collections and return new arrays. Equality comparison uses JSON value equality - numerically equivalent but differently formatted numbers (e.g., 0 versus 0.000) may not match. Empty arrays are valid inputs and follow mathematical conventions: empty union returns empty, empty intersection returns empty, sum of empty returns 0, product of empty returns 1.

Access Control Patterns

Check if a user possesses required permissions from a set. Verify that subjects hold all mandatory roles before granting access.

policy "require_admin_or_editor"
permit action == "modify_content"
where
    var required = ["admin", "editor"];
    array.containsAny(subject.roles, required);

Combine permissions from multiple sources when evaluating group memberships or inherited roles.

policy "aggregate_permissions"
permit
where
    var direct = subject.directPermissions;
    var inherited = subject.groupPermissions;
    var allOfSubjectsPermissions = array.union(direct, inherited);
    array.containsAll(allOfSubjectsPermissions, ["read", "write"]);

Find common capabilities between user privileges and resource requirements to determine allowed operations.

policy "intersection_access"
permit
where
    var allowed = array.intersect(subject.capabilities, resource.requirements);
    !array.isEmpty(allowed);
obligation
    {
        "type": "limit_operations",
        "operations": allowed
    }

Validate approval workflows by checking that signatories appear in the correct sequence. Enforce that approvals happen in order without gaps.

policy "approval_sequence"
permit action == "finalize_transaction"
where
    var required = ["manager", "director", "cfo"];
    array.containsAllInOrder(resource.approvals, required);

Calculate aggregate metrics for rate limiting or quota enforcement. Sum request counts or average response times across time windows.

policy "rate_limit"
deny action == "api_call"
where
    var counts = subject.requestsPerMinute;
    array.sum(counts) > 100;

array.isEmpty(Array array)

array.isEmpty(ARRAY array)

Returns true if the array has no elements.

Parameters:

  • array: Array to test

Returns: Boolean indicating whether array is empty

Example:

policy "example"
permit
where
    !array.isEmpty(subject.permissions);

array.containsAllInOrder(Array array, Array elements)

array.containsAllInOrder(ARRAY array, ARRAY elements)

Returns true if the array contains all elements from the elements array in the same sequential order, though not necessarily consecutively. Returns true if the elements array is empty.

Parameters:

  • array: Array to search in
  • elements: Elements that must appear in this order

Returns: Boolean indicating whether elements appear in order

Example - verify approval workflow sequence:

policy "example"
permit action == "finalize_contract"
where
    var required = ["legal_review", "manager_approval", "director_signature"];
    array.containsAllInOrder(resource.approvalSteps, required);

array.rangeStepped(Number from, Number to, Number step)

array.rangeStepped(NUMBER from, NUMBER to, NUMBER step)

Creates an array containing integers from from to to (both inclusive), incrementing by step. The step can be positive or negative. Returns an error if step is zero. All parameters must be integers. For positive step, from must be less than or equal to to. For negative step, from must be greater than or equal to to. Range is inclusive on both ends.

Parameters:

  • from: Starting value (inclusive)
  • to: Ending value (inclusive)
  • step: Increment value (positive or negative, not zero)

Returns: Array of integers with specified step

Example:

policy "example"
permit
where
    array.rangeStepped(1, 10, 2) == [1, 3, 5, 7, 9];
    array.rangeStepped(10, 1, -2) == [10, 8, 6, 4, 2];

array.head(Array array)

array.head(ARRAY array)

Returns the first element of the array. Returns an error if the array is empty.

Parameters:

  • array: Array to extract from

Returns: First element

Example:

policy "example"
permit
where
    array.head(subject.roles) == "admin";

array.sum(Array array)

array.sum(ARRAY array)

Returns the sum of all numeric elements in the array. Returns 0 for an empty array. All elements must be numeric or an error is returned.

Parameters:

  • array: Array of numbers to sum

Returns: Sum of all elements

Example - enforce rate limit:

policy "example"
deny action == "api_call"
where
    array.sum(subject.requestCounts) > 1000;

array.min(Array array)

array.min(ARRAY array)

Returns the minimum value from the array. For numeric arrays, returns the smallest number. For string arrays, returns the first string in lexicographic order. All elements must be of the same type. Returns an error for empty arrays, mixed types, or unsupported types.

Parameters:

  • array: Array to find minimum in

Returns: Minimum value

Example:

policy "example"
permit
where
    array.min(subject.securityLevels) >= 3;

array.range(Number from, Number to)

array.range(NUMBER from, NUMBER to)

Creates an array containing all integers from from to to (both inclusive). Returns an empty array if the range is invalid (from greater than to). Both parameters must be integers.

Parameters:

  • from: Starting value (inclusive)
  • to: Ending value (inclusive)

Returns: Array of consecutive integers

Example:

policy "example"
permit
where
    array.range(1, 5) == [1, 2, 3, 4, 5];

array.avg(Array array)

array.avg(ARRAY array)

Returns the arithmetic mean (average) of all numeric elements in the array. Returns an error for empty arrays. All elements must be numeric.

Parameters:

  • array: Array of numbers to average

Returns: Average value

Example:

policy "example"
permit
where
    array.avg(subject.performanceScores) >= 8.0;

array.reverse(Array array)

array.reverse(ARRAY array)

Returns the array with its elements in reversed order.

Parameters:

  • array: Array to reverse

Returns: New array with elements in reverse order

Example:

policy "example"
permit
where
    array.reverse([1, 2, 3, 4]) == [4, 3, 2, 1];

array.containsAny(Array array, Array elements)

array.containsAny(ARRAY array, ARRAY elements)

Returns true if the array contains at least one element from the elements array. Returns false if no elements are found or if the elements array is empty.

Parameters:

  • array: Array to search in
  • elements: Elements to search for

Returns: Boolean indicating whether any element was found

Example - check if user has any admin role:

policy "example"
permit action == "admin_panel"
where
    var adminRoles = ["superadmin", "admin", "moderator"];
    array.containsAny(subject.roles, adminRoles);

array.crossProduct(Array array1, Array array2)

array.crossProduct(ARRAY array1, ARRAY array2)

Returns the Cartesian product of two arrays. The result is an array of 2-element arrays, where each element contains one item from array1 paired with one item from array2. Returns an empty array if either input array is empty.

Parameters:

  • array1: First array
  • array2: Second array

Returns: Array of all possible pairs

Example - generate permission-resource combinations:

policy "example"
permit
where
    var actions = ["read", "write"];
    var resources = ["doc1", "doc2"];
    var combinations = array.crossProduct(actions, resources);
    combinations == [ ["read" , "doc1"], ["read" , "doc2"], ["write" , "doc1"], ["write" , "doc2"]];

array.median(Array array)

array.median(ARRAY array)

Returns the median value of all numeric elements in the array. The median is the middle value when the numbers are sorted. For arrays with an even number of elements, returns the average of the two middle values. Returns an error for empty arrays. All elements must be numeric.

Parameters:

  • array: Array of numbers to find median of

Returns: Median value

Example:

policy "example"
permit
where
    array.median([1, 2, 3, 4, 5]) == 3;
    array.median([1, 2, 3, 4]) == 2.5;

array.toSet(Array array)

array.toSet(ARRAY array)

Creates a copy of the array preserving the original order but removing all duplicate elements. Keeps the first occurrence of each element.

Parameters:

  • array: Array to deduplicate

Returns: New array with unique elements

Example:

policy "example"
permit
where
    array.toSet([1, 2, 3, 4, 3, 2, 1]) == [1, 2, 3, 4];

array.concatenate(Array arrays…)


Creates a new array by appending all parameter arrays in order. Preserves element
order within each array and the order of array parameters. Duplicates are retained.

Parameters:
- arrays: Arrays to concatenate

Returns: New array containing all elements in order

Example:
```sapl
policy "example"
permit
where
    array.concatenate([1, 2], [3, 4], [5]) == [1, 2, 3, 4, 5];

array.sort(Array array)

array.sort(ARRAY array)

Returns a new array with elements sorted in ascending order. The function determines the sort order based on the type of the first element. Numeric arrays are sorted numerically, string arrays are sorted lexicographically. All elements must be of the same type. Returns an error for mixed types, or unsupported types.

Numeric sorting uses floating-point comparison for performance, which is appropriate for SAPL’s authorization policy use cases. Very large integers beyond 2^53 may lose precision during comparison.

Parameters:

  • array: Array to sort

Returns: New sorted array

Example:

policy "example"
permit
where
    array.sort([3, 1, 4, 1, 5, 9, 2, 6]) == [1, 1, 2, 3, 4, 5, 6, 9];
    array.sort(["dog", "cat", "bird", "ant"]) == ["ant", "bird", "cat", "dog"];

array.difference(Array array1, Array array2)

array.difference(ARRAY array1, ARRAY array2)

Returns the set difference between array1 and array2, removing duplicates. Creates a new array containing elements from array1 that do not appear in array2.

Parameters:

  • array1: Array to subtract from
  • array2: Array of elements to remove

Returns: New array with elements in array1 but not in array2

Example - remove revoked permissions:

policy "example"
permit
where
    var granted = subject.grantedPermissions;
    var revoked = subject.revokedPermissions;
    var effective = array.difference(granted, revoked);
    array.containsAll(effective, resource.requiredPermissions);

array.intersect(Array arrays…)


        Creates a new array containing only elements present in all parameter arrays.
        Removes duplicates from the result, preserving order from the first array.

        Parameters:
        - arrays: Arrays to intersect

        Returns: New array with common elements

        Example - find shared permissions:
```sapl
policy "example"
permit
where
    var adminPerms = ["read", "write", "delete"];
    var editorPerms = ["read", "write"];
    var viewerPerms = ["read"];
    var common = array.intersect(adminPerms, editorPerms, viewerPerms);
    common == ["read"];

array.containsAll(Array array, Array elements)

array.containsAll(ARRAY array, ARRAY elements)

Returns true if the array contains all elements from the elements array. The elements do not need to appear in the same order. Returns true if the elements array is empty.

Parameters:

  • array: Array to search in
  • elements: Elements that must all be present

Returns: Boolean indicating whether all elements were found

Example - verify user has all required permissions:

policy "example"
permit action == "publish_article"
where
    var required = ["write", "publish", "notify"];
    array.containsAll(subject.permissions, required);

array.isSet(Array array)

array.isSet(ARRAY array)

Returns true if the array contains only distinct elements with no duplicates. An empty array is considered a set.

Parameters:

  • array: Array to test

Returns: Boolean indicating whether array is a set

Example:

policy "example"
permit
where
    array.isSet([1, 2, 3, 4]);
    !array.isSet([1, 2, 3, 2]);

array.multiply(Array array)

array.multiply(ARRAY array)

Returns the product of all numeric elements in the array. Returns 1 for an empty array. All elements must be numeric or an error is returned.

Parameters:

  • array: Array of numbers to multiply

Returns: Product of all elements

Example:

policy "example"
permit
where
    array.multiply([2, 3, 4]) == 24;

array.max(Array array)

array.max(ARRAY array)

Returns the maximum value from the array. For numeric arrays, returns the largest number. For string arrays, returns the last string in lexicographic order. All elements must be of the same type. Returns an error for empty arrays, mixed types, or unsupported types.

Parameters:

  • array: Array to find maximum in

Returns: Maximum value

Example:

policy "example"
permit
where
    array.max([3, 1, 4, 1, 5, 9]) == 9;

array.union(Array arrays…)


Creates a new array containing all unique elements from all parameter arrays.
Removes duplicates while preserving the first occurrence of each element.

Parameters:
- arrays: Arrays to combine

Returns: New array with all unique elements

Example - combine permissions from multiple sources:
```sapl
policy "example"
permit
where
    var all = array.union(subject.directPermissions, subject.groupPermissions);
    array.containsAll(all, ["read", "write"]);

array.flatten(Array array)

array.flatten(ARRAY array)

Flattens a nested array structure by one level. Takes an array that may contain other arrays and returns a new array with all nested arrays expanded into the top level.

Parameters:

  • array: Array to flatten

Returns: New flattened array

Example:

policy "example"
permit
where
    array.flatten([1, [2, 3], 4, [5]]) == [1, 2, 3, 4, 5];

array.size(Array value)

array.size(ARRAY value)

Returns the number of elements in the array.

Parameters:

  • value: Array to measure

Returns: Integer count of elements

Example:

policy "example"
permit
where
    array.size(subject.roles) >= 2;

array.zip(Array array1, Array array2)

array.zip(ARRAY array1, ARRAY array2)

Combines two arrays element-wise into an array of 2-element arrays (pairs). The resulting array has length equal to the shorter of the two input arrays.

Parameters:

  • array1: First array
  • array2: Second array

Returns: Array of paired elements

Example:

policy "example"
permit
where
    array.zip([1, 2, 3], ["a", "b", "c"]) == [[1, "a"], [2, "b"], [3, "c"]];

array.last(Array array)

array.last(ARRAY array)

Returns the last element of the array. Returns an error if the array is empty.

Parameters:

  • array: Array to extract from

Returns: Last element

Example:

policy "example"
permit action == "finalize"
where
    array.last(resource.approvals) == "cfo_signature";