# Policy examples

The examples described below cover different business cases that you can use as a basis for creating your own.

You can implement the examples in one of the following ways:

- With the `policies` payload of the `genesis` operation you run at system setup. For more information about this payload, see the example in [Run system setup](/products/custody/v1.34/deployment/install/installation#policies).
- With the `payload` of the `v0_CreatePolicy` intent. For more information about this payload, see the example in [Ripple Custody API > Create policies](/products/custody/v1.34/api/environment/policy/create#payload-example).


## Roles

The following table gives an overview of the roles used in the examples:

| Role | Type | Description |
|  --- | --- | --- |
| `system-operator` | Maker | Human user in charge of the entities of the environment who creates and submits organizational intents (for example, user and account creation, vault registration). |
| `policy-operator` | Maker | Human user in charge of environment administration. |
| `transaction-operator` | Maker | Human user in charge of the operational entities of the environment who creates and submits operational intents (for example, transaction order creation). |
| `transaction-operator-bot` | Maker | Technical, or bot, user with the same rights as the human `transaction-operator`. |
| `compliance` | Checker | Human user in charge of signing and approving operational and management intents submitted by users with any other type of role. |


Both human and bot users are included in the examples, with a minimum of two users recommended for all human roles.

For a description of maker and checker roles, see [Central principles of the policy framework](/products/custody/v1.34/get-started/design/policies/overview#central-principles-of-the-policy-framework).

## Organizational policies

The following set of example policies applies to organizational tasks.

### User management

This policy is for user management operations, including creation of new users, updates to
user roles, locking and unlocking users.

The policy has the following characteristics:

- The intent type is set to a list of the different available actions for users so the policy is
applicable to user intents, as long as the condition is met.
- The condition specifies that the intent can be requested by users with `system-operator` role.
- The intent must be approved by a second user with `system-operator` role.


| Policy property | JSON example |
|  --- | --- |
| Intent types | `["v0_CreateUser", "v0_UpdateUser", "v0_LockUser", "v0_UnlockUser"]` |
| Conditions | {   "expression": "context.references.users[context.request.author.id].roles.includes('system-operator')",   "type": "Expression"} |
| Workflows | [  {    "role": "system-operator",      "quorum": 2,    "type": "RoleQuorum"   }    ] |


### Account management

This policy is for account management operations, including creation of new accounts, updates to existing accounts, locking and unlocking accounts.

The policy has the following characteristics:

- The intent type is set to a list of the different available actions for accounts so the policy is
applicable to account intents, as long as the condition is met.
- The condition specifies that the intent can be requested by users with `system-operator` role.
- The intent must be approved by a second user with `system-operator` role and by a `compliance`
role.


| Policy property | JSON example |
|  --- | --- |
| Intent types | `["v0_CreateAccount", "v0_UpdateAccount", "v0_LockAccount","v0_UnlockAccount"]` |
| Conditions | {   "expression": "context.references.users[context.request.author.id].roles.includes('system-operator')",    "type": "Expression"} |
| Workflows | [   {      "left": {     "role": "system-operator",         "quorum": 2,         "type": "RoleQuorum"      },      "right": {          "role": "compliance",            "quorum": 1,          "type": "RoleQuorum"      },      "type": "And"   }] |


### Endpoint management – register a trusted address

This policy is for the management of endpoints that register trusted addresses, including creation of endpoints, updates to existing endpoints, locking and unlocking endpoints.

The policy has the following characteristics:

- The intent type is set to a list of the different available actions for endpoints so the policy
is applicable to endpoint intents, as long as the condition is met.
- The condition specifies that the intent can be requested by users with `system-operator` role.
- The intent must be approved by a second user with `system-operator` role.


| Policy property | JSON example |
|  --- | --- |
| Intent types | `["v0_CreateEndpoint" , "v0_UpdateEndpoint" , "v0_LockEndpoint" , "v0_UnlockEndpoint"]` |
| Conditions | {    "expression": "context.references.users[context.request.author.id].roles.includes('system-operator')",    "type": "Expression"} |
| Workflows | [   {      "role": "system-operator",      "quorum": 2,      "type": "RoleQuorum"   }] |


### Endpoint management – register a smart contract

This policy is for the creation of endpoints that represent smart contracts.

The policy has the following characteristics:

- The intent type is set to create endpoints, so the other operations (update, lock, and
unlock) match the previous policy. Note that the rank of this policy is higher than the generic
endpoint policy as it must be evaluated first, otherwise the previous policy applies.
- The condition specifies that the intent can be requested by users with `system-operator` role and
that the `parameters` object must exist with a non-null value. This parameter object contains the ABI
definition, so this indicates that the address belongs to a smart contract.
- The intent must be approved by a second user with either `system-operator` role, and then
escalated to a `compliance` user.


| Policy property | JSON example |
|  --- | --- |
| Intent types | `["v0_CreateEndpoint" ]` |
| Conditions | {    "expression": "context.references.users[context.request.author.id].roles.includes('system-operator') &&context.request.payload.hasOwnProperty('parameters') &&context.request.payload.parameters != null",    "type": "Expression"} |
| Workflows | [   {      "role": "system-operator",      "quorum": 2,      "type": "RoleQuorum"   },   {      "role": "compliance",     "quorum": 1,     "type": "RoleQuorum"   }] |


## Policy management

This policy is to manage other policies, including the creation, update, locking and unlocking
of policies. Generally a policy to update policies needs to have a high rank to be applied first. This policy enables the correction of other policies when mistakes occur.

The policy has the following characteristics:

- The intent type is set to a list of the different available actions for policies so the policy is
applicable to policy intents, as long as the condition is met.
- The condition specifies that the order can be requested by users with `policy-operator` role.
The intent must be approved by a second user with a `policy-operator` role and two `compliance`
roles.
- The policy needs an appropriately high-risk approval workflow, as creating and
modifying policies is an extremely sensitive operation.


| Policy property | JSON example |
|  --- | --- |
| Intent types | `["v0_CreatePolicy", "v0_UpdatePolicy", "v0_LockPolicy","v0_UnlockPolicy"]` |
| Conditions | {   "expression": "context.references.users[context.request.author.id].roles.includes('policy-operator')",   "type": "Expression"} |
| Workflows | [   {      "left": {         "role": "policy-operator",         "quorum": 2,         "type": "RoleQuorum"      },      "right": {         "role": "compliance",         "quorum": 2,         "type": "RoleQuorum"      },      "type": "And"   }] |


## Transaction policies

The following set of example policies applies to transaction tasks.

### Transfer out to an unknown address (XRPL and ETH)

This policy is for transaction orders where the destination is an unknown ledger address. The policy applies to XRPL and Ethereum Virtual Machine ledgers.

The policy has the following characteristics:

- The intent type is set to `v0_CreateTransactionOrder` so the policy is applicable to
transaction order intents, as long as the condition is met.
- The condition specifies that the order can be requested by users with `transaction-operator` role
and that the destination is an address. Before checking for the destination type, we check if a
`destination.type` object exists. This is because for some ledgers (other than XRPL and ETH) the
structure of the payload is different and the data at this location does not exist, which will trigger an
error in the policy.
- The order must be approved by a second user with either `transaction-operator` role and two
`compliance` roles.


| Policy property | JSON example |
|  --- | --- |
| Intent types | `["v0_CreateTransactionOrder"]` |
| Conditions | {   "expression": "context.references.users[context.request.author.id].roles.includes('transaction-operator') &&context.request.payload.parameters.hasOwnProperty('destination') &&context.request.payload.parameters.destination.type == 'Address'",   "type": "Expression"} |
| Workflows | [   {      "left": {         "role": "transaction-operator",         "quorum": 2,         "type": "RoleQuorum"      },      "right": {         "role": "compliance",         "quorum": 2,         "type": "RoleQuorum"      },      "type": "And"   }] |


### Transfer out to a trusted address (XRPL and ETH)

This policy is for transaction orders where the destination is a trusted address. A trusted address is an
address registered as an endpoint where the trust score is set to a value higher than a threshold. For
this example, the threshold is set to 75.

The policy has the following characteristics:

- The intent type is set to `v0_CreateTransactionOrder` so the policy applicable to
transaction order intents as long as the condition is met.
- The condition specifies that the order can be requested by users with either `transaction-operator`
role or `transaction-operator-bot` role, and that the destination is an endpoint with a score greater than 75. Before
checking for the destination type, we check if a `destination.type` object exists. This is because for
some ledgers (other than XRPL and ETH) the structure of the payload is different and the data at this
location does not exist, which will trigger an error in the policy.
- The order must be approved by a second user with either `transaction-operator` role or
`transaction-operator-bot` role.


| Policy property | JSON example |
|  --- | --- |
| Intent types | `["v0_CreateTransactionOrder"]` |
| Conditions | {   "expression": "(context.references.users[context.request.author.id].roles.includes('transaction-operator-bot') ||context.references.users[context.request.author.id].roles.includes('transaction-operator') ) &&context.request.payload.parameters.hasOwnProperty('destination') &&context.request.payload.parameters.destination.type == 'Endpoint' &&context.references.endpoints[context.request.payload.parameters.destination.endpointId].trustScore >= 75",   "type": "Expression"} |
| Workflows | [   {      "left": {         "role": "transaction-operator",          "quorum": 1,         "type": "RoleQuorum"      },      "right": {         "role": "transaction-operator-bot",         "quorum": 1,         "type": "RoleQuorum"      },      "type": "Or"   },   {      "left": {         "role": "transaction-operator",         "quorum": 1,         "type": "RoleQuorum"      },      "right": {         "role": "transaction-operator-bot",         "quorum": 1,         "type": "RoleQuorum"      },      "type": "Or"   }] |


### Transfer out of ETH with a large amount (irrespective of destination)

This policy is for transaction orders where the amount is higher than a defined threshold.

The policy has the following characteristics:

- The intent type is set to `v0_CreateTransactionOrder` so the policy is applicable to
transaction order intents as long as the condition is met.
- The condition specifies that the order can be requested by users with `transaction-operator` role, that the source account is from a specific ledger (in this case `ethereum-testnet`) and that
the amount is greater than 5 ETH.
- The order must be approved by two users with `compliance` role.


| Policy property | JSON example |
|  --- | --- |
| Intent types | `["v0_CreateTransactionOrder"]` |
| Conditions | {   "expression": "context.references.users[context.request.author.id].roles.includes('transaction-operator') &&context.references.accounts[context.request.payload.accountId].ledgerId == 'ethereum-testnet' &&context.request.payload.parameters.amount >= BigInt(5000000000000000000)",   "type": "Expression"} |
| Workflows | [   {      "left": {         "role": "transaction-operator",         "quorum": 1,         "type": "RoleQuorum"      },      "right": {         "role": "compliance",         "quorum": 2,         "type": "RoleQuorum"      },      "type": "And"   }] |


### Transfer out of BTC with a large amount (irrespective of destination)

This policy is for transaction orders where the amount is higher than a defined threshold.

The policy has the following characteristics:

- The intent type is set to `v0_CreateTransactionOrder` so the policy is applicable to
transaction order intents as long as the condition is met.
- The condition specifies that the order can be requested by users with `transaction-operator` role,
that the source account is from a specific ledger (in this case `bitcoin-testnet`) and that the amount
is greater than 5 BTC.
- The order must be approved by two users with `compliance` role.


| Policy property | JSON example |
|  --- | --- |
| Intent types | `["v0_CreateTransactionOrder"]` |
| Conditions | {   "expression": "context.references.users[context.request.author.id].roles.includes('transaction-operator') && context.references.accounts[context.request.payload.accountId].ledgerId == 'bitcoin-testnet' && contextrequest.payload.parameters.outputs.reduce((acc, v) => BigInt(acc) + BigInt(v.amount), 0) >= BigInt(500000000)",   "type": "Expression"} |
| Workflows | [   {      "left": {         "role": "transaction-operator",         "quorum": 1,         "type": "RoleQuorum"      },      "right": {         "role": "compliance",         "quorum": 2,         "type": "RoleQuorum"      },      "type": "And"   }] |


### Transfer in

This policy is to manage anti-money laundering (AML) on incoming funds. All incoming funds are put under
quarantine with no exception and must be explicitly released.

The policy has the following characteristics:

- The intent type is set to `v0_ReleaseQuarantinedTransfers` so the policy is applicable to
transaction order intents as long as the condition is met.
- The condition specifies that the order can be requested by users with `system-operator` role.
- The approval workflow consists of the approval of the maker role `system-operator`, and a further
approval from one `compliance` role


| Policy property | JSON example |
|  --- | --- |
| Intent types | `["v0_ReleaseQuarantinedTransfers"]` |
| Conditions | {   "expression": "context.references.users[context.request.author.id].roles.includes('system-operator')",   "type": "Expression"} |
| Workflows | [   {     "left": {         "role": "system-operator",         "quorum": 1,         "type": "RoleQuorum"      },      "right": {         "role": "compliance",         "quorum": 1,         "type": "RoleQuorum"      },      "type": "And"   }] |


## Catch-all

A catch-all policy is always recommended as a fail-safe mechanism to capture business workflows
that have not been accounted for. This may be due to a new business requirement being introduced
or to a use case not previously accounted for.

We recommend that the catch-all policy is associated with a high-risk approval workflow, since the purpose of this
policy is to catch exceptions and not be a standard policy for regular business flows.

This policy also needs a particularly low rank, to ensure that the system first tries to look for
an existing policy and only resorts to using the catch-all if no other system policy can govern an intent.

The policy has the following characteristics:

- The intent type is set to `null` so the policy is applicable to all types of intents as long as the
condition is met.
- The condition specifies that the user must have one of the maker roles named above. This is to
ensure that any other user without one of the maker roles is not able to propose an intent. In
a more general case, the condition could also be set to `null`, to further capture any attempt to create
an intent.
- The approval consists of a quorum of two `compliance` roles. The first step of the
approval workflow is a combination of workflow objects, to enable any of the maker roles to give the first approval.


| Policy property | JSON example |
|  --- | --- |
| Conditions | {   "expression":   "context.references.users[context.request.author.id].roles.includes('system-operator') || context.references.users[context.request.author.id].roles.includes('policy-operator') || context.references.users[context.request.author.id].roles.includes('transaction-operator')",  "type": "Expression"} |
| Workflows | [   {      "left": {         "left": {            "role": " system-operator ",            "quorum": 1,            "type": " RoleQuorum "         },         "right": {            "role": " policy-operator ",            "quorum": 1,            "type": " RoleQuorum "         },         "type": "Or"      },      "right": {         "role": "transaction-operator",         "quorum": 1,         "type": " RoleQuorum "      },      "type": "Or"   },   {      "role": "compliance",      "quorum": 2,      "type": "RoleQuorum"   }] |