PolicyFlow

Policies Overview

Understanding the structure and components of PolicyFlow policies

Policies are the core logic components of PolicyFlow. They define the authorization rules that determine whether a user can perform an action on a resource in a given context.

Policy Declaration

A policy begins with a declaration that includes its unique name and optional metadata:

/**
 * This policy controls access to financial reports.
 * It is a critical component of our SOX compliance.
 */
policy ReportingAccess {
    // A human-readable summary of the policy's purpose
    description: "Controls read and export access for quarterly financial reports."

    // Version tag for tracking changes (does not affect evaluation)
    version: "1.2.0"

    // Tags for organization, filtering, and discovery
    tags: ["finance", "sox", "reporting", "pii"]

    // ... policy body ...
}

Policy Structure

A complete policy consists of several key sections:

1. Imports

Import the schemas and types your policy will use:

import * as Auth from "@/schemas/auth.pfs:AuthSchema";
import * as Finance from "@/schemas/finance.pfs:FinanceSchema";

2. Metadata (Optional)

Provide information about the policy. Note that the version field is purely informational and does not affect policy evaluation or deployment:

policy FinancialReporting {
    description: "Manages access to financial reports"
    version: "2.1.0"  // This is just a tag for human reference
    tags: ["finance", "compliance"]

    // ... rest of policy ...
}

The version field can be used to:

  • Track changes in your version control system
  • Document policy evolution
  • Help with change management processes
  • Provide context in audit logs

However, PolicyFlow does not use the version for:

  • Policy selection or routing
  • Backward compatibility
  • Version-based evaluation

3. Action Filtering (Optional)

Specify which actions this policy handles:

policy DocumentPolicy {
    actions: [
        "documents:read",
        "documents:write",
        "documents:delete",
        "documents:**"  // All document actions
    ]

    // ... rest of policy ...
}

4. Schema Declaration

Define the types of User, Resource, and Context this policy applies to:

policy DocumentAccess {
    schemas {
        User from Auth.CorporateUser
        Resource from Docs.Document
        Context from Web.RequestContext
    }

    // ... rest of policy ...
}

5. Rules

The heart of the policy - the authorization logic:

policy DocumentAccess {
    rules {
        rule OwnerAccess {
            when user.id == resource.ownerId
            then ALLOW
            reason: "Document owner has full access"
        }

        rule AdminOverride {
            when "admin" in user.roles
            then ALLOW
            priority: 1000
            reason: "Administrators have full access"
        }
    }
}

6. Default Decision

Policies in PolicyFlow are secure by default. If a request is evaluated against a policy and none of its rules produce an ALLOW decision, the policy's outcome is implicitly DENY. You do not need to specify a default decision; the system is designed to "fail closed" for maximum security.

Complete Policy Example

Here's a comprehensive example that demonstrates all the concepts:

import * as Auth from "@/schemas/auth.pfs:AuthSchema";
import * as Docs from "@/schemas/documents.pfs:DocumentSchema";
import * as Context from "@/schemas/context.pfs:ContextSchema";

/**
 * Controls access to corporate documents based on classification,
 * ownership, and user attributes.
 */
policy CorporateDocumentAccess {
    description: "Comprehensive document access control policy"
    version: "3.0.0"  // Just a tag - doesn't affect evaluation
    tags: ["documents", "security", "compliance"]

    // Only handle document-related actions
    actions: ["documents:**"]

    // Define the types this policy works with
    schemas {
        User from Auth.CorporateUser where user.isActive
        Resource from Docs.CorporateDocument
        Context from Context.WebRequest
    }

    // Helper function for checking business hours
    function isBusinessHours(): Boolean {
        const hour = DateTime.Now().ToUnit(TimeUnit.Hours);
        const day = DateTime.Now().DayOfWeek(); // 0=Sun, 6=Sat
        return day >= 1 AND day <= 5 AND hour >= 9 AND hour < 17;
    }

    rules {
        // Rule 1: Deny access outside of business hours for non-admins
        rule DenyOutsideBusinessHours {
            when !isBusinessHours() AND !("admin" in user.roles)
            then DENY
            priority: 1000
            reason: "Access is restricted to business hours (9am-5pm, Mon-Fri)"
        }

        // Rule 2: Owners always have access
        rule OwnerAccess {
            when user.id == resource.ownerId
            then ALLOW
            reason: "Resource owner"
        }

        // Rule 3: Admins have full access
        rule AdministratorAccess {
            when "admin" in user.roles
            then ALLOW
            priority: 1000
            reason: "Administrator privilege"
        }

        // Rule 4: Department members can access internal docs
        rule DepartmentAccess {
            when user.department == resource.department
                AND resource.classification == "Internal"
                AND action in ["documents:read", "documents:write"]
            then ALLOW
            reason: "Same department access"
        }

        // Rule 5: Everyone can read public documents
        rule PublicReadAccess {
            when resource.classification == "Public"
                AND action == "documents:read"
            then ALLOW
            reason: "Public document read access"
        }

        // Rule 6: Deny access to archived documents
        rule DenyArchivedAccess {
            when resource.status == "Archived"
                AND !("archivist" in user.roles)
            then DENY
            priority: 1000
            reason: "Document is archived"
        }

        // Rule 7: Require strong authentication for confidential docs
        rule ConfidentialRequiresMFA {
            when resource.classification == "Confidential"
                AND context.authMethod != "mfa"
            then DENY
            priority: 2000
            reason: "Confidential documents require MFA"
        }
    }
}

Key Concepts

Rule Evaluation Order

Rules are evaluated in order, but the final decision depends on priorities and conflict resolution:

  1. Rules are evaluated sequentially
  2. Each rule produces ALLOW, DENY, or no decision (if condition is false)
  3. Priorities (0-10000, lower numbers first) affect evaluation order
  4. The engine uses "Deny-Overrides" strategy

Conditional Schemas

You can add conditions to schema declarations:

schemas {
    // Only active users from EU
    User from Auth.User where user.isActive AND user.region == "EU"

    // Only production databases
    Resource from DB.Database where resource.environment == "prod"

    // Only requests from internal network
    Context from Web.Request where context.ipAddress.Matches("10.0.0.0/8")
}

Policy Functions

Define reusable logic within a policy:

policy DataAccess {
    function hasValidSubscription(user: User): Boolean {
        return user.subscriptionStatus == "active"
            AND user.subscriptionExpiry > DateTime.Now();
    }

    function isHighRiskAction(action: String): Boolean {
        return action in ["delete", "export", "share-external"];
    }

    rules {
        rule RequireSubscription {
            when !hasValidSubscription(user) AND isHighRiskAction(action)
            then DENY
        }
    }
}

Next Steps