PolicyFlow

Built-in Libraries

Comprehensive reference for PolicyFlow's standard library

PolicyFlow provides a rich set of built-in libraries for common operations. These libraries are available in all policies without requiring imports. All built-in types (such as Email, URL, IPAddress) and libraries are globally available.

DateTime Library

The DateTime library provides comprehensive date and time manipulation capabilities.

Static Methods

MethodDescriptionReturns
DateTime.Now()Current date and timeDateTime
DateTime.Today()Today's date at midnightDateTime
DateTime.Parse(string, [pattern])Parse a datetime stringDateTime

Instance Methods

MethodDescriptionReturns
.Age()Years since the datetime until nowNumber
.DayOfWeek()Day of week (0=Sunday, 6=Saturday)Number
.Add(unit, amount)Add time to a datetimeDateTime
.Subtract(unit, amount)Subtract time from a datetimeDateTime
.Format(pattern)Format as stringString
.ToUnit(unit)Extract component (year, month, etc.)Number

Examples

rule CheckBusinessHours {
    when {
        const now = DateTime.Now();
        const hour = now.ToUnit(TimeUnit.Hours);
        const dayOfWeek = now.DayOfWeek();

        // Monday-Friday (1-5), 9 AM - 5 PM
        return dayOfWeek >= 1 AND dayOfWeek <= 5
            AND hour >= 9 AND hour < 17;
    }
    then ALLOW
    reason: "Access allowed during business hours"
}

rule CheckAge {
    when {
        const age = user.birthDate.Age();
        return age >= 18;
    }
    then ALLOW
    reason: "User is an adult"
}

Time Library

For working with time values without dates.

Static Methods

MethodDescriptionReturns
Time.Now()Current timeTime
Time.Parse(string)Parse a time stringTime

Examples

rule NightShiftAccess {
    when {
        const currentTime = Time.Now();
        const nightStart = Time.Parse("22:00:00");
        const nightEnd = Time.Parse("06:00:00");

        // Handle time wrapping around midnight
        return currentTime >= nightStart OR currentTime <= nightEnd;
    }
    then ALLOW
}

Duration Library

For representing and calculating time spans.

Creating Durations

MethodDescriptionReturns
Duration.FromUnit(unit, value)Create duration from unitDuration

Duration Methods

MethodDescriptionReturns
.TotalDays()Total days (including fractions)Decimal
.TotalHours()Total hours (including fractions)Decimal
.TotalMinutes()Total minutes (including fractions)Decimal
.TotalSeconds()Total seconds (including fractions)Decimal
.TotalMilliseconds()Total millisecondsNumber

Examples

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

        // Deny if less than 7 days until expiration
        return daysUntilExpiry < 7;
    }
    then DENY
    reason: "Resource expires in less than 7 days"
}

rule EnforceTimeout {
    when {
        const sessionDuration = DateTime.Now() - user.sessionStart;
        const hoursElapsed = sessionDuration.TotalHours();
        const maxHours = 8;

        return hoursElapsed > maxHours;
    }
    then DENY
    reason: "Session timeout after 8 hours"
}

Math Library

Mathematical operations and utilities.

Methods

MethodDescriptionReturnsInput Types
Math.Abs(num)Absolute valueSame as inputNumber or Decimal
Math.Min(n1, n2, ...)Minimum valueSame as inputNumber or Decimal
Math.Max(n1, n2, ...)Maximum valueSame as inputNumber or Decimal
Math.Round(decimal, places)Round to decimal placesDecimalDecimal
Math.Floor(decimal)Round downNumberDecimal
Math.Ceil(decimal)Round upNumberDecimal
Math.Sum(array)Sum of array elementsSame as array typeNumber[] or Decimal[]
Math.Avg(array)Average of array elementsDecimalNumber[] or Decimal[]

Type Handling

The Math library preserves types where possible:

  • Methods that accept both Number and Decimal return the same type as input
  • Math.Sum() returns Number for Number[] arrays, Decimal for Decimal[] arrays
  • Math.Avg() always returns Decimal for precision
  • Math.Floor() and Math.Ceil() always return Number

Examples

rule CheckRiskScore {
    when {
        // Working with Number arrays
        const scores: Number[] = [
            user.creditScore,
            user.behaviorScore,
            user.reputationScore
        ];

        const avgScore = Math.Avg(scores);  // Returns Decimal
        const minScore = Math.Min(...scores);  // Returns Number
        const totalScore = Math.Sum(scores);  // Returns Number

        // Require average > 70 and no score below 50
        return avgScore > 70.0 AND minScore >= 50;
    }
    then ALLOW
}

rule CalculateTransactionFees {
    when {
        // Working with Decimal arrays
        const fees: Decimal[] = [
            resource.baseFee,
            resource.serviceFee,
            resource.processingFee
        ];

        const totalFees = Math.Sum(fees);  // Returns Decimal
        const avgFee = Math.Avg(fees);     // Returns Decimal

        // Apply 10% discount if total fees exceed threshold
        const discountedTotal = totalFees > 50.0
            ? totalFees * 0.9
            : totalFees;

        return discountedTotal <= user.maxFeeLimit;
    }
    then ALLOW
}

rule LimitTransactionAmount {
    when {
        // Mixed numeric operations
        const dailyTransactions: Decimal[] = user.todayTransactions;
        const dailyTotal = Math.Sum(dailyTransactions);  // Returns Decimal
        const proposedTotal = dailyTotal + resource.amount;

        // Different limits based on user tier
        const limit = user.isPremium ? 10000.0 : 1000.0;

        return proposedTotal > limit;
    }
    then DENY
    reason: "Daily transaction limit exceeded"
}

Runtime Library

For dynamic type inspection and safe property access.

Methods

MethodDescriptionReturns
Runtime.IsType(value, "TypeName")Check if value is of typeBoolean
Runtime.HasProperty(obj, "prop")Check if property existsBoolean
Runtime.GetProperty(obj, "prop")Get property valueAny

Examples

rule CheckDynamicAttribute {
    when {
        // user.metadata is Map<String, Any>
        if (!Runtime.HasProperty(user.metadata, "clearanceLevel")) {
            return false;
        }

        const clearance = Runtime.GetProperty(user.metadata, "clearanceLevel");
        return clearance >= resource.requiredClearance;
    }
    then ALLOW
}

rule ValidateCustomFields {
    when {
        // Check multiple dynamic properties
        const hasAllFields = Runtime.HasProperty(resource.customData, "approver")
            AND Runtime.HasProperty(resource.customData, "approvalDate")
            AND Runtime.HasProperty(resource.customData, "approvalReason");

        if (!hasAllFields) {
            return false;
        }

        // Validate approval is recent
        const approvalDate = Runtime.GetProperty(resource.customData, "approvalDate");
        const timeSinceApproval = DateTime.Now() - approvalDate;
        return timeSinceApproval.TotalDays() <= 30;
    }
    then ALLOW
}

Relationships Library

For querying the relationship graph between entities.

Methods

MethodDescriptionReturns
Relationships.Has(entity1, "relation", entity2)Check direct relationshipBoolean
Relationships.GetRelated(entity, "relation")Get related entitiesArray
Relationships.PathExists(e1, "path", e2)Check path existenceBoolean
Relationships.GetRelationship(e1, "relation", e2)Get relationship object with attributesRelationship?

Path Syntax

Paths use dots to chain relationships:

  • "member_of" - Direct relationship
  • "member_of.owns" - Two-hop path
  • "member_of.parent_of.owns" - Multi-hop path

Relationship Object Methods

When you retrieve a relationship object using GetRelationship, you can access its attributes.

MethodDescriptionReturns
.GetAttribute(key, [default])Get an attribute from the relationshipAny?

Examples

rule TeamMemberAccess {
    when Relationships.Has(user, "member_of", resource.team)
    then ALLOW
    reason: "User is a team member"
}

rule HierarchicalAccess {
    when {
        // Check if user manages the resource owner
        const manages = Relationships.PathExists(
            user,
            "manages.manages.manages",  // Up to 3 levels
            resource.owner
        );

        return manages AND action == "read";
    }
    then ALLOW
    reason: "Managers can read their reports' resources"
}

rule CollaboratorAccess {
    when {
        // Get the relationship object to check its attributes
        const rel = Relationships.GetRelationship(user, "collaborates_on", resource);
        if (rel == null) {
            return false;
        }

        // Check an attribute on the relationship itself
        const permissions = rel.GetAttribute("permissions");
        return permissions?.Contains("edit") ?? false;
    }
    then ALLOW
}

Crypto Library

For secure hashing and comparison operations. Never use for encryption.

Methods

MethodDescriptionReturns
Crypto.Sha256(input)SHA-256 hashString
Crypto.ConstantTimeCompare(s1, s2)Timing-safe comparisonBoolean
Crypto.Verify(plainText, hash)Verify password/secretBoolean

Security Best Practices

rule VerifyAPIKey {
    // BEST: Use Verify for password/secret validation
    when Crypto.Verify(context.apiKey, resource.apiKeyHash)
    then ALLOW
    reason: "Valid API key"
}

rule VerifyToken {
    // GOOD: Use constant-time comparison for hashes
    when {
        const providedHash = Crypto.Sha256(context.token + resource.salt);
        return Crypto.ConstantTimeCompare(providedHash, resource.tokenHash);
    }
    then ALLOW
}

// NEVER: Don't use regular comparison for secrets
// when Crypto.Sha256(context.secret) == resource.secretHash  // VULNERABLE TO TIMING ATTACKS!

Environment Variables

Access global configuration through the env map. Values from .env files are automatically parsed into String, Number, Decimal, or Boolean types. For detailed information about type detection and usage patterns, see the Language Syntax guide.

// .env file:
// ADMIN_ROLE = "system-admin"
// MAINTENANCE_MODE = false
// API_RATE_LIMIT = 1000

rule AdminAccess {
    when env["ADMIN_ROLE"] in user.roles
    then ALLOW
    priority: 1000
}

rule MaintenanceMode {
    when env["MAINTENANCE_MODE"] == true
    then DENY
    priority: 0
    reason: "System under maintenance"
}

rule RateLimit {
    when {
        const limit = env["API_RATE_LIMIT"];
        return user.requestCount > limit;
    }
    then DENY
    reason: "Rate limit exceeded"
}

Next Steps