Skip to main content

Introduction

The Policy Engine is your platform's source of truth for access control. Declare rules once; the engine enforces them everywhere — across transactions, key operations, and any action your platform exposes.

Capabilities

  • Multi-chain support: Allow for setting rules to secure digital assets held across multiple chains using a single, unified policy language model.
  • Offchain operations: Enforces policies for key export, key refresh, quorum change and other off-chain operations.
  • Transfer Limits: Cap the amount of value that can be transferred in a single transaction.
  • Fine-grained Access Control: Enables distributed authority across organizational boundaries where signature authority is split among multiple parties/levels.
  • Specific Architecture: Designed for transactions signed by Multi-Party Computation (MPC) nodes.
  • Key-Bound: Policies are bound to a specific Key ID.
  • Stateless & Deterministic: Evaluation is based solely on the request payload and the policy itself.
  • Auditable: Policy evaluation results are logged for every action.

Concepts

A Policy is a JSON document that defines the complete set of constraints for a key. Policy contains multiple Rule. A Rule might contain single Condition or multiple ones, called ConditionGroup.

  • Rule: A composite statement about if the transaction/request satisfies all the condition groups or conditions to execute the action.
  • Condition: A boolean statement that evaluates a specific attribute of the transaction (e.g., checking if amount is less than 100).
  • ConditionGroup: A combination of boolean statements about the transaction/request.

Validation: Policies are stored on external storage. Their integrity is ensured by using a Message Authentication Code (MAC).

Policy Structure

A Policy object follows this structure:

FieldTypeDescription
versionstringMust be "1.0".
descriptionstringOptional description (max 512 chars).
rulesRule[]List of rules to evaluate.

Rule Structure

FieldTypeDescription
descriptionstringOptional description (max 512 chars).
issuerIssuer[]Entities authorized to issue the request that will be evaluated by the engine.
actionstring"allow", "deny". The action to take if the conditions evaluate to true.
logicstringThe logic operator to use while combining result of the conditions. Can be "or", or "and". Defaults to "and" if omitted.
chain_typestring"off", "ethereum", "solana".
conditionsCondition[]List of conditions or condition groups.

Issuer

Defines who is making the request which is defined by the authentication payload in the request.

  • type: "UserId", "SessionKeyId", or "*" (any).
  • id: Depending on the type from above.
    • For UserId is the specific ID of the credential (for example: Passkey ID, or EOA address, or in case of no-auth architecture, the name of the registered Backend).
    • For SessionKeyId is the Ephemeral Key ID.

Conditions

Conditions are the building blocks of rules. They compare transaction attributes against expected values. They are logic statements that evaluate to true or false.

Condition Fields

FieldTypeDescription
transaction_typestringThe type of transaction (see below).
transaction_attrstringThe specific attribute to check (see below).
operatorstringComparison operator.
valueanyThe static value to compare against.
abiobject(Optional) ABI/IDL for decoding data.

Transaction Types

Used to deserialize the transaction payload correctly.

  • eip712: Typed Data signing.
  • eip191: Personal Sign.
  • erc20: Fungible Token interaction.
  • erc721: NFT interaction.
  • nativeTransfer: Pure ETH/SOL transfer.
  • solanaTransaction: General Solana transaction.

Transaction Attributes

The specific field within the transaction to evaluate.

NameDescriptionExample
senderTransaction sender. EIP-1559 "from" field in erc20, erc721 and ETH transfer transactions"0x742d35Cc6634C0532925a3b844Bc454e4438f44e"
receiverTransaction destination. EIP-1559 "to" field in erc20, erc721 and ETH transfer transactions. Or, sender account key in SOL transfer transaction"0x538f44e32925a3b844Bc454e4438f44e742d35Cc"
nativeValueAmount of native token (ETH/SOL)."1000000000000000000" (1 ETH)
chainIdBlockchain Network ID.1
functionSelectorEthereum function signature (4 bytes)."0xa9059cbb"
messageEIP-191 message content."Sign this message"
verifyingContractEIP-712 contract address."0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
primaryTypeEIP-712 primary type."Mail"
domainNameEIP-712 domain name."Ether Mail"
splTransferAmountSolana SPL token amount.1000000
splTokenMintSolana SPL token mint address."EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
solanaAccountKeysList of accounts in a Solana transaction.["Account1...", "Account2..."]

If an attribute is not found in the list above, the engine will try to resolve it as a parameter from the provided ABI. To resolve naming collisions between built-in attributes and ABI parameters, you can use the abi: prefix (e.g. abi:sender). This forces the engine to look up the attribute in the ABI parameters instead of using the built-in value.

Operators

The operands to evaluate Transaction Attributes against the Policy’s expected values.

  • eq: Equal
  • neq: Not Equal
  • lt: Less Than
  • lte: Less Than or Equal
  • gt: Greater Than
  • gte: Greater Than or Equal
  • in: Value is in a list.
  • all: All values match (for arrays).

Policy evaluation flow

Policy

A Policy evaluation is based on the results of Rule evaluations:

  • The Policy is evaluated rule-by-rule, in order as they are defined.
  • Precedence: If any rule evaluates to DENY, whole policy evaluates to DENY.
  • Default Behavior: If the request does not match to any of the rules in the policy, the whole policy evaluates to DENY.
  • If there's no Policy attached to the key, policy evaluation will never happen - that results in ALLOW ALL behavior for given key.

Rule

A Rule defines an action (ALLOW or DENY) that is triggered when:

  • The request Issuer and the Transaction Type matches the Policy configuration. If these 2 attributes aren't matched, the evaluation will be skipped for that Rule.
  • Conditions (or Condition Groups) are satisfied.

Example

Giving following example of the Policy:

{
"version": "1.0",
"description": "Example policy",
"rules": [
{
"issuer": [{"type": "UserId", "id": "alice"}],
"description": "Rule 1",
"action": "allow",
"logic": "and",
"conditions": [
{
"logic": "and"
"group": [
{ ...Condition1... },
{ ...Condition2... }
]
},
{
"logic": "and"
"group": [
{ ...Condition3... },
{ ...Condition4... }
]
},
]
}, // End of Rule 1
{
"issuer": [{"type": "UserId", "id": "alice"}],
"description": "Rule 2",
"action": "allow",
"logic": "or",
"conditions": [
{
"logic": "and"
"group": [
{ ...Condition5... },
{ ...Condition6... }
]
},
{
"logic": "or"
"group": [
{ ...Condition7... },
{ ...Condition8... }
]
},
]
} // End or Rule 2
]
}

It consists two Rules.

  • Rule1 has 2 Groups and logic operator AND
    • Group1 has 2 Conditions and logic operator AND
    • Group2 has 2 Conditions and logic operator AND
  • Rule2 has 2 Groups and logic operator OR
    • Group1 has 2 Conditions and logic operator AND
    • Group2 has 2 Conditions and logic operator OR
  • The whole policy is for issuer Alice

This example Policy can be seen as following logic statement:

( (C1 AND C2)  AND (C3 AND C4) ) AND ( (C5 AND C6) OR (C7 OR C8) )

As a tree:

             [AND]              - At Rules level, all rules are evaluated using AND.
/ \ That means, all must return `Allow` for policy to pass.
/ \ If any rule returns `Deny`, then whole policy returns `Deny`.
/ \
[AND] [OR] - Logic operators on Rule level
/ \ / \
[AND] [AND] [AND] [OR] - Logic operators on Condition group level
/ \ / \ / \ / \
C1 C2 C3 C4 C5 C6 C7 C8 - Conditions

Limitations

  • Stateless: No access to historical data (e.g., "Daily Limit" is not supported).
  • No External State: Cannot reference external price feeds or databases.
  • No Time Awareness: Cannot restrict based on time of day.