Facts
Facts are named input values that can be injected into policy evaluation. They serve as the primary mechanism for providing external data to policies, enabling them to make decisions based on runtime information.
Fact Declaration
Section titled “Fact Declaration”Basic Syntax
Section titled “Basic Syntax”-- Required fact (default behavior)fact <name>: <type> ('as' <exposed_name>)?
-- Optional fact (can have default)fact <name>?: <type> ('as' <exposed_name>)? ('default' <default_value>)?Required vs Optional Facts
Section titled “Required vs Optional Facts”-- Required fact (must be provided during execution, default behavior)fact user: User as user
-- Optional fact (can be omitted, marked with ?)fact context?: Context as context default { "key": "value" }Fact Types and Constraints
Section titled “Fact Types and Constraints”Primitive Types
Section titled “Primitive Types”-- Required facts (must be provided)fact userId: string as idfact isActive: bool as active
-- Optional facts with defaultsfact score?: number as points default 0fact price?: number as cost default 0.0fact name?: string as userName default "anonymous"Collection Types
Section titled “Collection Types”-- Required collection factsfact permissions: list[string] as userPermissions
-- Optional collection facts with defaultsfact metadata?: map[string] as userMetadata default {}fact coordinates?: record[number, number] as location default [ 0.0, 0.0 ]Shape Types
Section titled “Shape Types”shape User { id!: string role!: string permissions!: list[string]}
-- Required shape factfact user: User as currentUser
-- Optional shape fact with defaultfact user?: User as currentUser default { "id": "", "role": "guest", "permissions": [] }Fact Modifiers
Section titled “Fact Modifiers”Required Facts (Default)
Section titled “Required Facts (Default)”Facts are required by default. They must be provided during policy execution, and they cannot have default values.
-- Required fact - must be provided during evaluationfact user: User as user
-- This will cause an error: required facts cannot have defaults-- fact user: User as user default { "id": "", "role": "guest" } -- Error!Optional Facts (?)
Section titled “Optional Facts (?)”Use the ? operator to mark a fact as optional. Optional facts can be omitted during execution, and they can have default values.
-- Optional fact - can be omitted during evaluationfact context?: Context as context
-- Optional fact with default valuefact context?: Context as context default { "key": "value" }
-- If not provided, the default value will be used (if specified)-- If no default is provided and the fact is omitted, it simply won't be availableImportant
- Facts are always non-nullable - Even if a fact is optional, if it is provided, it cannot be null
- The
!operator is not supported for facts - facts are always non-nullable by design - Only optional facts (
?) can have default values
Default Values
Section titled “Default Values”Literal Defaults
Section titled “Literal Defaults”Default values can only be used with optional facts (marked with ?).
-- String defaults (optional facts)fact name?: string as userName default "anonymous"
-- Numeric defaults (optional facts)fact count?: number as itemCount default 0fact rate?: number as interestRate default 0.05
-- Boolean defaults (optional facts)fact enabled?: bool as isEnabled default true
-- Collection defaults (optional facts)fact tags?: list[string] as itemTags default []fact config?: map[string] as settings default {}Error
Required facts cannot have default values. This will cause a compilation error:
-- This will cause an errorfact name: string as userName default "anonymous" -- Error: required fact cannot have defaultShape Defaults
Section titled “Shape Defaults”shape Product { id!: string name!: string price!: number}
-- Optional fact with shape defaultfact product?: Product as currentProduct default { "id": "", "name": "Unknown", "price": 0.0}Fact Injection
Section titled “Fact Injection”During Policy Import
Section titled “During Policy Import”-- Import policy with fact injectionrule authResult = import decision of canAccess from com/example/auth/userAccess with user as { "id": "123", "role": "admin", "permissions": ["read", "write"] }Multiple Fact Injection
Section titled “Multiple Fact Injection”-- Inject multiple factsrule result = import decision of processOrder from com/example/orders/orderProcessing with user as currentUser with order as orderData with context as requestContextType Safety
Section titled “Type Safety”Runtime Validation
Section titled “Runtime Validation”-- Type validation: This will cause a type errorfact user?: User as user default { "id": 123 } -- Error: string expected, got number
-- Correct usagefact user?: User as user default { "id": "123" }
-- Null validation: Facts cannot be null-- This will cause a runtime error if null is providedfact user: User as user -- If null is provided, error: "fact 'user' cannot be null"Best Practices
Section titled “Best Practices”Use Descriptive Names
Section titled “Use Descriptive Names”-- Good: Clear, descriptive fact namesfact currentUser?: User as user default { "id": "", "role": "guest" }fact orderData?: Order as order default { "id": "", "items": [] }
-- Avoid: Generic or unclear namesfact data?: User as d default { "id": "", "role": "guest" }Provide Sensible Defaults
Section titled “Provide Sensible Defaults”-- Good: Meaningful default values for optional factsfact user?: User as user default { "id": "anonymous", "role": "guest", "permissions": [] }
-- Avoid: Confusing or invalid defaultsfact user?: User as user default { "id": "", "role": "invalid", "permissions": null } -- null not allowedUse Required Facts Appropriately
Section titled “Use Required Facts Appropriately”-- Good: Use required facts for data that must always be providedfact userId: string as id -- Must be provided, no default allowed
-- Good: Use optional facts with defaults for data that has sensible fallbacksfact context?: Context as ctx default { "environment": "production" }
-- Avoid: Making everything required when defaults would be appropriatefact userId: string as id -- If this often has a default, consider making it optionalfact userId?: string as id default "anonymous" -- Better if default makes sense