PolicyFlow

Type Methods Reference

Complete reference of methods available for each type

Every type in PolicyFlow has specific methods that can be called on instances of that type. This reference provides a comprehensive guide to all available methods.

String Methods

Strings provide extensive text manipulation capabilities.

Methods Reference

MethodDescriptionReturnsExample
.Length()Number of charactersNumber"hello".Length()5
.Lower()Convert to lowercaseString"HELLO".Lower()"hello"
.Upper()Convert to uppercaseString"hello".Upper()"HELLO"
.Trim()Remove whitespaceString" hello ".Trim()"hello"
.Contains(substring)Check substring existenceBoolean"hello".Contains("ell")true
.StartsWith(prefix)Check string startBoolean"hello".StartsWith("he")true
.EndsWith(suffix)Check string endBoolean"hello".EndsWith("lo")true
.Matches(regex)Match regular expressionBoolean"test@example.com".Matches("^[^@]+@[^@]+$")true
.Split(delimiter)Split into arrayString[]"a,b,c".Split(",")["a", "b", "c"]

Static Methods

MethodDescriptionReturnsExample
String.Join(array, delimiter)Join array elementsStringString.Join(["a", "b"], ",")"a,b"

Examples

rule ValidateEmail {
    when {
        const email = user.email.Lower().Trim();

        // Check domain
        if (!email.EndsWith("@company.com")) {
            return false;
        }

        // Check format
        if (!email.Matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$")) {
            return false;
        }

        // Check length
        return email.Length() > 5 AND email.Length() < 100;
    }
    then ALLOW
}

rule ParseTags {
    when {
        const tags = resource.tags.Split(",").Map(t => t.Trim().Lower());
        return tags.Contains("public") OR tags.Contains("shared");
    }
    then ALLOW
}

Array Methods

Arrays provide powerful collection manipulation methods.

Methods Reference

MethodDescriptionReturns
.Count()Number of elementsNumber
.IsEmpty()Check if emptyBoolean
.Contains(element)Check element existenceBoolean
.Distinct()Remove duplicatesArray
.First()Get first elementElement?
.Last()Get last elementElement?
.Intersection(other)Common elementsArray
.Union(other)Combined unique elementsArray

Lambda Methods

MethodDescriptionReturns
.Any(x => condition)Check if any matchBoolean
.All(x => condition)Check if all matchBoolean
.Filter(x => condition)Filter elementsArray
.Map(x => transform)Transform elementsArray

Examples

rule CheckPermissions {
    when {
        const requiredPerms = ["read", "write", "delete"];
        const userPerms = user.permissions;

        // Check if user has all required permissions
        return requiredPerms.All(p => userPerms.Contains(p));
    }
    then ALLOW
}

rule ValidateRoles {
    when {
        const adminRoles = ["admin", "super-admin", "system-admin"];
        const userRoles = user.roles.Map(r => r.Lower());

        // Check if user has any admin role
        return adminRoles.Any(role => userRoles.Contains(role));
    }
    then ALLOW
}

rule CheckTags {
    when {
        const allowedTags = resource.allowedTags;
        const requestedTags = context.requestedTags;

        // All requested tags must be in allowed tags
        const invalidTags = requestedTags.Filter(t => !allowedTags.Contains(t));
        return invalidTags.IsEmpty();
    }
    then ALLOW
}

Map Methods

Maps (dictionaries) provide key-value storage and lookup.

Methods Reference

MethodDescriptionReturns
.Count()Number of entriesNumber
.IsEmpty()Check if emptyBoolean
.ContainsKey(key)Check key existenceBoolean
.Get(key, [default])Get value with optional defaultValue?
.Keys()Get all keysArray<Key>
.Values()Get all valuesArray<Value>

Bracket Notation

// These are equivalent:
const value1 = map.Get("key");
const value2 = map["key"];

// With default value:
const value3 = map.Get("key", "default");

Examples

rule CheckAttributes {
    when {
        // user.attributes is Map<String, String>
        const dept = user.attributes.Get("department", "unknown");
        const level = user.attributes["clearanceLevel"];

        return dept == "engineering" AND level != null;
    }
    then ALLOW
}

rule ValidateMetadata {
    when {
        const requiredKeys = ["owner", "classification", "created"];
        const metadata = resource.metadata;

        // Check all required keys exist
        return requiredKeys.All(key => metadata.ContainsKey(key));
    }
    then ALLOW
}

DateTime Methods

DateTime provides comprehensive date and time operations.

Instance Methods

MethodDescriptionReturns
.Age()Years until nowNumber
.DayOfWeek()Day (0=Sunday)Number
.Add(unit, amount)Add timeDateTime
.Subtract(unit, amount)Subtract timeDateTime
.Format(pattern)Format as stringString
.Time()Extract time componentTime
.ToUnit(unit)Extract componentNumber

Time Units

Use with TimeUnit enum:

  • TimeUnit.Years
  • TimeUnit.Months
  • TimeUnit.Days
  • TimeUnit.Hours
  • TimeUnit.Minutes
  • TimeUnit.Seconds

Examples

rule CheckAccountAge {
    when {
        const accountAge = (DateTime.Now() - user.createdAt).TotalDays();
        const isWeekend = DateTime.Now().DayOfWeek() in [0, 6];

        // Require 30-day old account for weekend access
        return !isWeekend OR accountAge >= 30;
    }
    then ALLOW
}

rule CheckExpiration {
    when {
        const timeUntilExpiry = resource.expiresAt - DateTime.Now();
        const hoursUntilExpiry = timeUntilExpiry.TotalHours();

        if (hoursUntilExpiry < 24) {
            return false;  // Deny if expires within 24 hours
        }

        const nextMonth = DateTime.Now().Add(TimeUnit.Months, 1);
        return resource.expiresAt < nextMonth;
    }
    then ALLOW
}

Specialized Type Methods

Email Methods

MethodDescriptionReturnsExample
.Domain()Full domainString"user@sub.example.com".Domain()"sub.example.com"
.LocalPart()Username partString"user@example.com".LocalPart()"user"
.TopLevelDomain()TLDString"user@example.co.uk".TopLevelDomain()"uk"

URL Methods

MethodDescriptionReturnsExample
.Scheme()ProtocolString"https://example.com".Scheme()"https"
.Host()Full hostnameString"https://api.example.com".Host()"api.example.com"
.Domain()Registered domainString"https://api.example.com".Domain()"example.com"
.Port()Port numberNumber?"https://example.com:8080".Port()8080
.Path()URL pathString"https://example.com/api/v1".Path()"/api/v1"
.GetQueryParam(key)Query parameterString?"https://example.com?key=value".GetQueryParam("key")"value"

IPAddress Methods

MethodDescriptionReturns
.IsIPv4()Check if IPv4Boolean
.IsIPv6()Check if IPv6Boolean
.Matches(cidr)Check CIDR matchBoolean

Examples

rule ValidateEmailDomain {
    when {
        const allowedDomains = ["company.com", "partner.com"];
        return allowedDomains.Contains(user.email.Domain());
    }
    then ALLOW
}

rule CheckInternalAccess {
    when {
        // Only allow internal IPs
        return context.ipAddress.Matches("10.0.0.0/8")
            OR context.ipAddress.Matches("192.168.0.0/16");
    }
    then ALLOW
}

rule ValidateAPIEndpoint {
    when {
        const url = context.requestUrl;

        // Must be HTTPS
        if (url.Scheme() != "https") {
            return false;
        }

        // Must be on allowed domain
        if (url.Domain() != "api.company.com") {
            return false;
        }

        // Check port if specified (Port() returns null if no port)
        const port = url.Port();
        if (port != null AND port != 443) {
            return false;
        }

        // Must be v2 API
        return url.Path().StartsWith("/v2/");
    }
    then ALLOW
}

rule HandleNullableReturns {
    when {
        // First() and Last() return null if array is empty
        const firstRole = user.roles.First();
        if (firstRole == null) {
            return false;  // No roles assigned
        }

        // GetQueryParam() returns null if parameter not found
        const apiKey = context.requestUrl.GetQueryParam("api_key");
        if (apiKey == null) {
            return false;  // No API key provided
        }

        // Map.Get() returns null if key not found (without default)
        const clearance = user.attributes.Get("clearanceLevel");
        if (clearance == null) {
            return false;  // No clearance level set
        }

        return true;
    }
    then ALLOW
}

Method Chaining

Methods can be chained for concise expressions:

rule ComplexValidation {
    when {
        // Chain string methods
        const normalizedEmail = user.email.Trim().Lower();

        // Chain array methods
        const activeAdmins = users
            .Filter(u => u.isActive)
            .Filter(u => u.roles.Contains("admin"))
            .Map(u => u.id);

        // Chain with null-safe operator
        const managerDept = user.manager?.department?.Upper() ?? "NONE";

        return normalizedEmail.EndsWith("@company.com")
            AND activeAdmins.Count() > 0
            AND managerDept == "ENGINEERING";
    }
    then ALLOW
}

Next Steps