# Technical Documentation – AML Ruleset Definition Language

# **DSL Schema Documentation for Transaction Rulesets**

## **Overview**

This DSL (Domain-Specific Language) defines ruleset-based conditions for handling transactions. The rulesets specify
conditions under which transactions should be blocked, allowed, or flagged. The schema enables defining logical
conditions using `AND`, `OR`, `request_property_check`, `transactions_volume_check`, `transactions_quantity_check`,
`blacklist_check`,
`greylist_check`, `kyc_property_check` and `compare_with_last_transaction`
statements, along with customizable triggers and actions.

---

## **Schema Structure**

```yaml
conditions:
  AND | OR: # Logical operator grouping conditions
    - request_property_check: # Check type
        property: <string>  # The property to check (e.g., "transactionData.acquirerCountry")
        comparator: <string>  # enums: "IN", "NOT_IN", "=", "!=", ">", ">=", "<", "<=", "CONTAINS"
        value: <string | list | variable>  # Expected value or variable reference, eg: string: "123", list: "value1, value2, value3" or variable (`{{ vars.UHRC_COUNTRIES }}`)
        treat_missing_value_as: <boolean>  # optional, How to handle missing fields (default: false)
    - transactions_volume_check:
        scope: <string> # enums: CORPORATION, USER, CARD, BALANCE
        by: <string> # optional, enums: MERCHANT, COUNTRY, grouping parameter
        period: <string> # 1d -> 1 day, 1M -> one month etc.
        amount: <number> # cumulative amount for given scope/by and period, as minor > 50000
        currency: <string> # country currency codes e.g. PLN, USD, AOA
        currencyAggregation: <string> # enums: SAME_CURRENCY_ONLY, CONVERT_TO_CURRENCY
        filters: # optional
          - field: <string>> #enum: type, subtype, transactionData.merchantName, transactionData.mcc, transactionData.countryCode, transactionData.contrahentName, transactionData.captureMode
            comparator: <string>  # enums: "IN", "NOT_IN", "=", "!="
            value: ATM # <string | list | variable>
    - transactions_quantity_check:
        scope: BALANCE # enums: CORPORATION, USER, CARD, BALANCE
        by: COUNTRY # optional, enums: MERCHANT, COUNTRY, grouping parameter
        period: <string> # 1d -> 1 day, 1M -> one month etc.
        quantity: 5 # transactions count for given scope/by and period, > 5
        filters: # optional
          - field: <string>> #enum: type, subType, transactionData.merchantName, transactionData.mcc, transactionData.countryCode, transactionData.contrahentName, transactionData.captureMode
            comparator: <string>  # enums: "IN", "NOT_IN", "=", "!="
            value: ATM # <string | list | variable>
    - kyc_property_check:
        property: <string>
        comparator: <string> # enums: "IN", "NOT_IN", "=", "!=", ">", ">=", "<", "<=", "CONTAINS"
        value: <string | list | variable>
        treat_missing_value_as: <boolean>  # optional, How to handle missing fields (default: false)
    - blacklist_check:
        properties:
          - property: <string> # blacklist record property
            kyc_value: <string> # user's KYC record property to evaluate
          - property: <string> # blacklist record property
            request_value: <string> # aml-verify request property to evaluate
    - greylist_check:
        properties:
          - property: <string> # greylist record property
            kyc_value: <string> # user's KYC record property to evaluate
          - property: <string> # greylist record property
            request_value: <string> # aml-verify request property to evaluate
    - compare_with_last_transaction:
        options:
          within_seconds: <number> # time in seconds
          subType: list<string> # types of transactions will be searched for in the transaction history, e.g. ["ATM_WITHDRAWAL", "PURCHASE"]
          context: <string> # enums: CARD, BALANCE, BALANCE_OWNER
          captureMode: list<string> # Payment channel/method (e.g. CONTACT, CONTACTLESS, ECOMMERCE, CLOUD, MONEYSEND, etc.)
        property: <string> # The property to check in history transaction (e.g., "transactionData.acquirerCountry")
        comparator: <string> # enums: "IN", "NOT_IN", "=", "!=", ">", ">=", "<", "<=", "CONTAINS"
        request_property: <string> # The property to check in request (e.g., "transactionData.acquirerCountry")
        treat_missing_value_as: <boolean> # optional, How to handle missing fields (default: false)

    - AND | OR:
        - request_property_check: null
          field: <string>
        #...
trigger:
  decision: <string>  # enum ( APPROVED, DECLINED)
  actions:
    <group>: # Action group
      - name: <string> # Action name (e.g. block_resource)
        properties:
          <key>: <value> # Action properties (e.g. reason: fraud_suspected, resource_type: user)
  alert:
    channels: <string> # enum: YOUTRACK_TICKET, USER_PUSH_NOTIFICATION, USER_EMAIL_NOTIFICATION
    cooldown_period: <string> # optional, 1d -> 1 day, 1M -> one month etc.
  balance_owner_notifications:
    - type: <string> # enum: SMS, EMAIL
      template_name: <string> # notification template name
      cooldown_period: <string> # optional, 1d -> 1 day, 1M -> one month etc.
```

---

## **Field Descriptions**

### **Top-Level Fields**

| Field        | Type     | Description                                         |
|--------------|----------|-----------------------------------------------------|
| `conditions` | `Object` | Defines logical conditions using `AND` / `OR`.      |
| `trigger`    | `Object` | Specifies what happens when the conditions are met. |

### **Condition Fields**

| Field                           | Type     | Description                                                                      |
|---------------------------------|----------|----------------------------------------------------------------------------------|
| `AND` / `OR`                    | `List`   | Groups multiple conditions where all (`AND`) or at least one (`OR`) must be met. |
| `request_property_check`        | `Object` | Specifies a [request property](#bkmrk-request-property-che) condition check.         |
| `kyc_property_check`            | `Object` | Specifies a [kyc value](#bkmrk-kyc-check) check.                                       |
| `transactions_volume_check`     | `Object` | Specifies a [transactions volume](#bkmrk-transactions-volume) check.             |
| `transactions_quantity_check`   | `Object` | Specifies a [transactions quantity](#bkmrk-transactions-quantit) check.         |
| `blacklist_check`               | `Object` | Specifies a [blacklist](#bkmrk-blacklist-and-greyli) check.                    |
| `greylist_check`                | `Object` | Specifies a [greylist](#bkmrk-blacklist-and-greyli) check.                     |
| `compare_with_last_transaction` | `Object` | Specifies a [last transaction](#bkmrk-last-transaction-che) check.                   |

### **Common check fields**

| Field                    | Type            | Description                                                                                                                                                                                                                                                                                              |
|--------------------------|-----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `comparator`             | `String`        | Comparison operator, enums: `IN`, `NOT_IN`, `=`, `!=`, `>`, `>=`, `<`, `<=`, `CONTAINS`, in case of date comparison uses ISO-8601 format for parsing date).                                                                                                                                              |
| `property`               | `String`        | The data field to evaluate (e.g., `transactionData.acquirerCountry`).                                                                                                                                                                                                                                    |
| `value`                  | `String`/`List` | The expected value in the form of: <br/> string `value`<br/> list `value1, value2, value3`<br/> or a reference to a variable called "Value set" `{{ vars.UHRC_COUNTRIES }}`. Reference variables must be defined in API or front end administration panel. Only defined reference variables are allowed. |
| `treat_missing_value_as` | `Boolean`       | Determines handling of missing fields (default `false`).                                                                                                                                                                                                                                                 |

### **Comparators**

Comparators are used to compare the value of a property with a given value.

| Comparator     | Accepted value type | Description                                                                                                            |
|----------------|---------------------|------------------------------------------------------------------------------------------------------------------------|
| `=`            | `String`            | Property value equals the given value string (case-insensitive).                                                       |
| `!=`           | `String`            | Property value does not equals the given value string (case-insensitive).                                              |
| `>`            | `String`            | Property value is greater than the given value string (case-insensitive).                                              |
| `>=`           | `String`            | Property value is greater than or equal the given value string (case-insensitive).                                     |
| `<`            | `String`            | Property value is less than the given value string (case-insensitive).                                                 |
| `<=`           | `String`            | Property value is less than or equal the given value string (case-insensitive).                                        |
| `IN`           | `List`              | Property value matches any of the strings in the given value list (case-sensitive).                                    |
| `NOT_IN`       | `List`              | Property value matches none of the strings in the given value list (case-sensitive).                                   |
| `CONTAINS`     | `String/List`       | Property value contains the given value string, or any string from the provided value list (case-insensitive)          |
| `NOT_CONTAINS` | `String/List`       | Property value does not contain the given value string, nor any string from the provided value list (case-insensitive) |

### **Request property check**

| Field                    | Type            | Description                                         |
|--------------------------|-----------------|-----------------------------------------------------|
| `property`               | `String`        | See [property](#bkmrk-common-check-fields).               |
| `comparator`             | `String`        | See [comparator](#bkmrk-comparators).                     |
| `value`                  | `String`/`List` | See [value](#bkmrk-common-check-fields).                  |
| `treat_missing_value_as` | `Boolean`       | See [treat_missing_value_as](#bkmrk-common-check-fields). |

### **Kyc check**

| Field                    | Type     | Description                                         |
|--------------------------|----------|-----------------------------------------------------|
| `property`               | `String` | The Kyc property to evaluate (e.g., `riskLvl`).     |
| `comparator`             |          | See [comparator](#bkmrk-common-check-fields).             |
| `value`                  |          | See [value](#bkmrk-common-check-fields).                  |
| `treat_missing_value_as` |          | See [treat_missing_value_as](#bkmrk-common-check-fields). |

### **Transactions volume check**

| Field                 | Type     | Description                                                                                                                                                                   | AML-Verify request mapping                                                                                                                                                                              |
|-----------------------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `scope`               | `String` | Defines the level at which the transaction volume is calculated. It determines whose transaction volume is being measured.<br>enums: `CORPORATION`, `USER`, `CARD`, `BALANCE` | `CORPORATION` → `balance.ownerId` (if balance.owner == CORPORATION)<br>`USER` → `balance.ownerId` (if balance.owner == USER)<br>`CARD` → `resourceId` (if resource == CARD)<br>`BALANCE` → `balance.id` |
| `by`                  | `String` | Specifies the parameter used to group transaction volume within the selected scope.<br>enums: `MERCHANT`, `COUNTRY`                                                           | `MERCHANT` → `transactionData.merchantIdentifier`<br>`COUNTRY` → `transactionData.acquirerCountry`                                                                                                      |
| `period`              | `String` | The time interval over which to aggregate transaction volume. See [periods](#bkmrk-periods)                                                                                         | -                                                                                                                                                                                                       |
| `amount`              | `Number` | Cumulative amount.                                                                                                                                                            | -                                                                                                                                                                                                       |
| `currency`            | `String` | Cumulative amount currency.                                                                                                                                                   | -                                                                                                                                                                                                       |
| `currencyAggregation` | `String` | Defines how transactions in different currencies are aggregated.                                                                                                              | -                                                                                                                                                                                                       |
| `filters`             | `List`   | See [transaction filters](#bkmrk-transaction-check-fi).                                                                                                                        | -                                                                                                                                                                                                       |

### **Transactions quantity check**

| Field      | Type     | Description                                                                                                                                                                       | AML-Verify request mapping                                                                                                                                                                              |
|------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `scope`    | `String` | Defines the level at which the transaction quantity is calculated. It determines whose transaction quantity is being measured.<br>enums: `CORPORATION`, `USER`, `CARD`, `BALANCE` | `CORPORATION` → `balance.ownerId` (if balance.owner == CORPORATION)<br>`USER` → `balance.ownerId` (if balance.owner == USER)<br>`CARD` → `resourceId` (if resource == CARD)<br>`BALANCE` → `balance.id` |
| `by`       | `String` | Specifies the parameter used to group transaction quantity within the selected scope.<br>enums: `MERCHANT`, `COUNTRY`                                                             | `MERCHANT` → `transactionData.merchantIdentifier`<br>`COUNTRY` → `transactionData.acquirerCountry`                                                                                                      |
| `period`   | `String` | The time interval over which to count transactions. See [periods](#bkmrk-periods)                                                                                                       | -                                                                                                                                                                                                       |
| `quantity` | `Number` | Transactions count.                                                                                                                                                               | -                                                                                                                                                                                                       |
| `filters`  | `List`   | See [transaction filters](#bkmrk-transaction-check-fi).                                                                                                                            | -                                                                                                                                                                                                       |

### **Blacklist and greylist check**

| Field           | Type     | Description                                                                                      |
|-----------------|----------|--------------------------------------------------------------------------------------------------|
| `property`      | `String` | The property from the blacklist/greylist record to be checked (e.g., `name`, `pesel`).           |
| `kyc_value`     | `String` | The user's KYC field that will be compared against the `property`. (e.g. `firstName`,`lastName`) |
| `request_value` | `String` | The request field (from `aml-verify` body) that will be compared against the `property`.         |

### **Last transaction check**

| Field                    | Type                   | Description                                                                             |
|--------------------------|------------------------|-----------------------------------------------------------------------------------------|
| `options.within_seconds` | `String`               | Time in seconds to search transaction history from.                                     |
| `options.subType`        | `List<String>`         | Last transaction subType, e.g. `ATM_WITHDRAWAL, PURCHASE`                               |
| `options.context`        | `String`               | Last transaction context, enums: `CARD, BALANCE, BALANCE_OWNER`                         |
| `options.captureMode`    | `List<String>`\|`null` | Last transaction captureMode, will be matched with event's `transactionData.channel`    |
| `property`               | `String`               | The property to check in history transaction (e.g., `transactionData.acquirerCountry`). |
| `comparator`             | `String`               | See [comparator](#bkmrk-common-check-fields).                                                 |
| `request_property`       | `String`               | The property to check in request (e.g., `transactionData.acquirerCountry`).             |
| `treat_missing_value_as` | `String`               | See [treat_missing_value_as](#bkmrk-common-check-fields).                                     |

### **Allowed values for fields inside ruleset parameters** ###

| Ruleset check type                    | Allowed value                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
|---------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Request property check `property`     | transactionId, balance.owner, balance.ownerId, resourceId, externalReferenceTransactionId, resource, type, subType, amount, currency, originalAmount, originalCurrency, status, description, transactionDate, tenantId, transactionData.mcc, transactionData.merchantIdentifier, transactionData.merchantName, transactionData.captureMode, transactionData.lastFourDigits, transactionData.acquirerCountry, transactionData.mdesDigitizedWalletId, transactionData.cashbackPosCurrencyCode, transactionData.cashbackPosAmount, transactionData.lastFourDpan, transactionData.adjustmentReasonDescription, transactionData.retrievalReferenceNumber, transactionData.contrahentName, transactionData.contrahentIban, transactionData.contrahentBic, customData.* |
| Kyc check `property`                  | status, tenantId, customerId, dcUserId, verificationId, firstName, lastName, birthDate, nationality, riskLvl, createdAt, usaResident, taxResident, sourceOfFunds, pesel, country, city, identityCardNo, documents                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| Blacklist / greylist check `property` | userId, tenantId, name, surname, fullName, birthDate, pesel, documentNumber, documentType, addressCountry, addressCity, iban                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| Last transaction check `property`     | transactionId,  eventTimestamp,  tenantId,  type,  subType,  amount,  currency,  status,  description,  card.cardOwner,  card.cardOwnerId,  balance.balanceOwner,  balance.balanceOwnerId,  transactionDate,  createdAt,  clearedAt,  externalTransactionId,  externalReferenceTransactionId,  transactionData.lastFourDigits,  transactionData.mcc,  transactionData.merchantName,  transactionData.channel,  transactionData.countryCode,  transactionData.originalAmount,  transactionData.originalCurrency,  transactionData.walletReference,  transactionData.contrahentName,  transactionData.contrahentBic,  transactionData.merchantId                                                                                                                   |

### **Trigger Fields**

| Field                         | Type     | Description                                                                                                                                                          |
|-------------------------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `decision`                    | `String` | The decision taken if the ruleset is triggered (`DECLINED`, `ON_HOLD`, `APPROVED`).                                                                                  |
| `actions`                     | `List`   | A list of actions executed when the ruleset is triggered. Actions and their properties must be defined in API. Only defined in API actions are allowed               |
| `alert`                       | `Object` | Definition of alerts that should be sent to internal channels (e.g. YouTrack).                                                                                       |
| `balance_owner_notifications` | `List`   | A list of direct notifications sent to the balance owner when the ruleset is triggered. See [balance owner notification fields](#bkmrk-balance-owner-notifi). |

### **Alert Fields**

| Field             | Type     | Description                                                                                                                          |
|-------------------|----------|--------------------------------------------------------------------------------------------------------------------------------------|
| `channels`        | `List`   | List of channels where send alert. Possible values: `YOUTRACK_TICKET, USER_PUSH_NOTIFICATION, USER_EMAIL_NOTIFICATION`               |
| `cooldown_period` | `String` | How long the sending of a repeated alert is suspended for a given (USER + TENANT) or (CORPORATION + TENANT). See [periods](#bkmrk-periods) |

### **Balance Owner Notification Fields**

| Field             | Type     | Description                                                                                                           |
|-------------------|----------|-----------------------------------------------------------------------------------------------------------------------|
| `type`            | `String` | Notification channel type. Possible values: `SMS`, `EMAIL`                                                            |
| `template_name`   | `String` | Name of the notification template to use.                                                                             |
| `cooldown_period` | `String` | Optional. How long sending of a repeated notification is suspended for a given balance owner. See [periods](#bkmrk-periods) |

### **Transaction check filters**

`[0-*]` filters to narrow the transaction history search.

Each filter consists of:

| Field        | Type                    | Description                                                                                                                                                                                    |
|--------------|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `field`      | `String`                | Filter field by. Possible values: `type, subType, transactionData.mcc, transactionData.countryCode, transactionData.merchantName, transactionData.contrahentName, transactionData.captureMode` |
| `comparator` | `String`                | See [comparator](#bkmrk-common-check-fields).                                                                                                                                                        |
| `value`      | `String`/`List<String>` | See [value](#bkmrk-common-check-fields).                                                                                                                                                             |

#### **Periods**

Allowed period values:

| Unit variants                | ChronoUnit |
|------------------------------|------------|
| Y, y, yr, year, years        | YEARS      |
| M, m, mo, mon, month, months | MONTHS     |
| w, week, weeks               | WEEKS      |
| d, day, days                 | DAYS       |
| h, hr, hour, hours           | HOURS      |
| min, mins, minute, minutes   | MINUTES    |

Additional literal values:

- `previous_month` – allowed only for **check period** (used by `TransactionsVolumeCheck` and
  `TransactionsQuantityCheck`); represents the full previous calendar month.

---

## **Key Aspects**

### Ruleset

The rulesets specify conditions under which transactions should be blocked, allowed, or flagged.
If a ruleset's conditions are true, its actions are executed.

### Conditions

Conditions are the core of each ruleset.
They can be simple or complex, using logical operators to combine multiple checks.
Conditions are evaluated using the logical operators specified.

### Actions

Actions are executed when a ruleset's conditions are met.
These can include any number of predefined actions, such as blocking a card or notifying a user.
Actions are executed in the order they appear in the list.
If multiple rulesets match with the transaction and contain an action, it will only be returned and executed once.

### Decision

If all rulesets return `APPROVED`, the final result = `APPROVED`.
If at least one ruleset returns `DECLINED`, the final result = `DECLINED`.
If no rulesets return `DECLINED` but at least one ruleset returns `ON_HOLD`, the final result = `ON_HOLD`.

---

## **Example Rulesets**

### **Example 1: Blocking Transactions from UHRC Countries for every Partner**

### **Ruleset description**

This ruleset blocks any transaction where the acquirer country belongs to the UHRC (Unusual High-Risk Countries) list.
It enforces a global AML policy and applies to all partners. Any transaction coming from high-risk jurisdictions is
automatically declined and reported through an alert.

```yaml
conditions:
  AND:
    - request_property_check:
        property: transactionData.acquirerCountry
        comparator: IN
        value: {{ vars.UHRC_COUNTRIES }}
        treat_missing_value_as: false
trigger:
  decision: DECLINED
  alert:
    channels: [ YOUTRACK_TICKET ]
```

---

### **Example 2: Additional Tenant and User ID Constraints**

### **Ruleset description**

This ruleset blocks UHRC transactions specifically for the Acme tenant. It excludes internal or system accounts based on
ownerId. When triggered, the user is also blocked at the Antaca level. It represents a stricter, tenant-specific AML
policy tailored for Acme.

```yaml
conditions:
  AND:
    - request_property_check:
        property: transactionData.acquirerCountry
        comparator: IN
        value: {{ vars.UHRC_COUNTRIES }}
    - request_property_check:
        property: tenantId
        comparator: =
        value: Acme
    - request_property_check:
        property: balance.ownerId
        comparator: NOT_IN
        value: [ 1,2,3 ]
trigger:
  decision: DECLINED
  actions:
    antaca:
      - name: block_resource
        properties:
          reason: fraud_suspected
          resource_type: user
```

---

### **Example 3: Structuring pattern in high-risk merchant categories**

### **Ruleset description**

This ruleset detects potential structuring (smurfing) behavior. If many small transactions or a high cumulative
transaction amount occurs in high-risk MCC categories within one day, an alert is generated. Transactions are approved
to avoid blocking—but the AML team is notified for review.

```yaml
conditions:
  OR:
    - transactions_volume_check:
        scope: BALANCE
        by: MERCHANT
        period: "1d"
        amount: 1500000
        currency: PLN
        filters:
          - field: transactionData.mcc
            comparator: IN
            value: {{ vars.HIGH_RISK_MCC }}
          - field: type
            comparator: "="
            value: "DEBIT"
    - transactions_quantity_check:
        scope: BALANCE
        by: MERCHANT
        period: "1d"
        quantity: 10
        filters:
          - field: transactionData.mcc
            comparator: IN
            value: {{ vars.HIGH_RISK_MCC }}
          - field: type
            comparator: "="
            value: "DEBIT"
trigger:
  decision: APPROVED
  alert:
    channels: [ YOUTRACK_TICKET ]
    cooldown_period: "1d"
```

---

### **Example 4: High KYC risk level or high risk nationality alert**

### **Ruleset description**

This ruleset identifies users with a high KYC risk level or with a nationality belonging to a high-risk jurisdiction. It
does not block transactions but produces an alert to highlight increased AML exposure and enable continuous monitoring
of risky users.

```yaml
conditions:
  OR:
    - kyc_property_check:
        property: riskLvl
        comparator: =
        value: HIGH
    - kyc_property_check:
        property: nationality
        comparator: IN
        value: {{ vars.UHRC_COUNTRIES }}
        treat_missing_value_as: true
trigger:
  decision: APPROVED
  alert:
    channels:
      - YOUTRACK_TICKET
```

---

### **Example 5: Blacklist match on personal or national identifiers**

### **Ruleset description**

This ruleset checks if the user matches any record in the blacklist based on personal identifiers such as PESEL, name,
surname, nationality, date of birth, or counterparty IBAN. If a match occurs, the transaction is declined and the user
is blocked. This ensures that individuals previously flagged for fraud or AML reasons cannot transact further.

```yaml
conditions:
  OR:
    - blacklist_check:
        properties:
          - property: pesel
            kyc_value: pesel
    - blacklist_check:
        properties:
          - property: iban
            request_value: transactionData.contrahentIban
    - blacklist_check:
        properties:
          - property: name
            kyc_value: firstName
          - property: surname
            kyc_value: lastName
          - property: addressCountry
            kyc_value: nationality
          - property: birthDate
            kyc_value: birthDate
trigger:
  decision: DECLINED
  actions:
    antaca:
      - name: block_resource
        properties:
          reason: fraud_suspected
          resource_type: user
```

---

### **Example 6: Rapid cross-border card transaction on terminal or ATM detection**

### **Ruleset description**

This ruleset detects impossible or highly suspicious card activity across borders. If two transactions occur within 300
seconds but originate from two different countries, the system assumes the card may be compromised. The transaction is
declined and an alert is raised, as physical cross-border movement is not feasible in such a short time.

```yaml
conditions:
  AND:
    - request_property_check:
        property: subType
        comparator: IN
        value: [ PURCHASE, ATM_WITHDRAWAL ]
    - request_property_check:
        property: transactionData.captureMode
        comparator: IN
        value: [ MAG, EMV, NFC ]
    - compare_with_last_transaction:
        options:
          within_seconds: 300
          subType: [ PURCHASE, ATM_WITHDRAWAL ]
          context: CARD
          captureMode: [ CONTACT, CONTACTLESS ]
        property: transactionData.countryCode
        comparator: "="
        request_property: transactionData.countryCode
        treat_missing_value_as: false
trigger:
  decision: DECLINED
  alert:
    channels: [ YOUTRACK_TICKET ]
```

### **Example 7: Unusual debit transaction with balance owner notifications**

### **Ruleset description**

This ruleset detects unusual debit transactions in gambling and casino-related merchant categories and notifies the
balance owner directly via SMS and EMAIL in addition to raising an internal alert. The MCC codes associated with
gambling are defined as a variable (`GAMBLING_MCC`). Both notifications have an optional cooldown period to avoid
spamming the user and use a predefined template.

```yaml
conditions:
  AND:
    - request_property_check:
        property: type
        comparator: =
        value: DEBIT
    - request_property_check:
        property: transactionData.mcc
        comparator: IN
        value: {{ vars.GAMBLING_MCC }}
trigger:
  decision: DECLINED
  alert:
    channels:
      - YOUTRACK_TICKET
    cooldown_period: 1d
  balance_owner_notifications:
    - type: SMS
      template_name: unusual_transaction_detected
      cooldown_period: 1d
    - type: EMAIL
      template_name: unusual_transaction_detected
      cooldown_period: 1d
```

### **Example 8: Monthly turnover threshold without extended verification**

### **Ruleset description**

This ruleset detects when a user without extended KYC verification exceeds the defined monthly turnover threshold in EUR
or PLN. When triggered, the system declines further transactions and requires the user to complete extended
verification.

```yaml
conditions:
  AND:
    - kyc_property_check:
        property: kycLevel
        comparator: "!="
        value: EXTENDED
        treat_missing_value_as: true
    - OR:
        - transactions_volume_check:
            scope: USER
            period: "1M"
            amount: 1000000
            currency: EUR
        - transactions_volume_check:
            scope: USER
            period: "1M"
            amount: 4300000
            currency: PLN
trigger:
  decision: DECLINED
  actions:
    antaca:
      - name: extended_verification_required
        properties:
          reason: monthly_turnover_exceeded
          resource_type: user
```

---

## **Tools**

- [kaml](https://github.com/charleskorn/kaml)
- [yamlkt](https://github.com/Him188/yamlkt)
- [jackson yaml](https://github.com/FasterXML/jackson-dataformats-text)