# policies.json

`policies.json` defines runtime guard policies for your Swytchcode project.

Unlike `tooling.json`, which controls **what can execute**, `policies.json` controls **when a tool is allowed to execute** based on the request being made.

Every policy is evaluated **before execution**, allowing you to block requests that violate your organization's rules.

The file lives at:

```
.swytchcode/integrations/policies.json
```

> **How it works**
>
> Before executing any method, Swytchcode checks whether a matching policy exists. If a policy condition evaluates to `true`, the configured action is applied immediately.

---

## Managing Policies

Swytchcode provides CLI commands for managing policies.

### Add a policy

```bash
swy policy add
```

Creates a new policy interactively.

---

### List policies

```bash
swy policy list
```

Displays every configured policy.

---

### Remove a policy

```bash
swy policy remove <policy-id>
```

Deletes a policy by its ID.

---

### Validate policies

```bash
swy policy validate
```

Validation checks for:

- Unknown operators
- Missing required fields
- Duplicate IDs
- Invalid action types
- Empty targets
- Invalid value types
- Dotted field paths
- Malformed nested conditions

Validation errors are reported with human-readable messages before execution.

---

### Review past violations

`swy policy` only manages the *rules* - it doesn't show you what's happened historically. Every time a policy blocks a request, Swytchcode logs the violation to a local, read-only history. To review it:

```bash
swy audit policy            # recent policy-violation entries
swy audit policy -n 20      # last 20 entries
swy audit policy --info <id>  # full detail for one violation (id looks like pol_...)
```

This is useful when a policy blocks something unexpectedly and you need to see exactly which field/value tripped the rule, without touching `policies.json` itself. See the [Command Reference](/reference/commands/#system) for the full `swy audit` surface.

---

## Fail-Closed Behavior

`policies.json` follows a fail-closed validation model.

| Situation | Behavior |
|-----------|----------|
| File does not exist | No policies are applied. Execution continues normally. |
| File exists and is valid | Policies are evaluated before execution. |
| File exists but is malformed | Execution stops with a validation error. |

This ensures invalid policy definitions never silently bypass security checks.

---

## File Structure

A minimal policy file looks like this:

```json
{
  "defaults": {
    "on_violation": "fail",
    "evaluation": "pre_execution"
  },
  "policies": [
    {
      "id": "star-repo-approval",
      "target": [
        "github.repo.star"
      ],
      "when": {
        "field": "name",
        "operator": "exists"
      },
      "action": {
        "type": "POLICY_BLOCKED",
        "message": "Starring repositories is blocked."
      }
    }
  ]
}
```

The file consists of two sections:

- `defaults`
- `policies`

---

## defaults

The `defaults` object defines how policy evaluation behaves.

```json
{
  "defaults": {
    "on_violation": "fail",
    "evaluation": "pre_execution"
  }
}
```

### on_violation

Determines what happens when a policy condition matches.

```json
{
  "on_violation": "fail"
}
```

Currently, only one value is supported.

| Value | Description |
|--------|-------------|
| `fail` | Immediately stops execution. |

Any other value fails validation.

---

### evaluation

Specifies when policies are evaluated.

```json
{
  "evaluation": "pre_execution"
}
```

Supported value:

| Value | Description |
|--------|-------------|
| `pre_execution` | Evaluate policies before any API request is made. |

Future versions may introduce additional evaluation stages.

---

## Policy Objects

Every rule inside the `policies` array represents a single guard.

Example:

```json
{
  "id": "block-large-payments",
  "target": [
    "stripe.create_payment"
  ],
  "when": {
    "field": "amount",
    "operator": ">",
    "value": 100000
  },
  "action": {
    "type": "POLICY_BLOCKED",
    "message": "Payments above the allowed limit are blocked."
  }
}
```

Each policy contains four required fields.

---

### id

A unique identifier for the policy.

```json
{
  "id": "block-large-payments"
}
```

If another policy uses the same ID, it replaces the existing policy.

---

### target

Defines which methods or workflows the policy protects.

```json
{
  "target": [
    "stripe.create_payment"
  ]
}
```

A policy only runs when one of these canonical IDs is executed.

Multiple tools can be protected.

```json
{
  "target": [
    "stripe.create_payment",
    "stripe.refund_payment"
  ]
}
```

---

### when

Defines the condition that triggers the policy.

```json
{
  "when": {
    "field": "amount",
    "operator": ">",
    "value": 100000
  }
}
```

If this condition evaluates to `true`, Swytchcode executes the configured action.

Conditions are covered in detail below.

---

### action

Defines what happens when a condition matches.

```json
{
  "action": {
    "type": "POLICY_BLOCKED",
    "message": "Payments above the limit are blocked."
  }
}
```

Both `type` and `message` are required.

---

## Action Types

Supported action types are:

| Action | Description |
|--------|-------------|
| `AUTH_FAILED` | Authentication failed. |
| `POLICY_BLOCKED` | Request blocked by policy. |

Example:

```json
{
  "action": {
    "type": "POLICY_BLOCKED",
    "message": "Too many requests."
  }
}
```

When a policy blocks execution:

- the request is never sent
- execution stops immediately
- Swytchcode exits with code **4**

---

## Conditions

Conditions determine when a policy should apply.

There are two types:

- Leaf conditions
- Group conditions

---

## Leaf Conditions

Leaf conditions compare a single request field.

Example:

```json
{
  "field": "amount",
  "operator": ">",
  "value": 100000
}
```

Swytchcode evaluates the resolved request arguments before execution.

---

## Group Conditions

Group conditions combine multiple rules.

They use one of three logical operators.

| Operator | Description |
|----------|-------------|
| `all` | Every condition must match (AND). |
| `any` | At least one condition must match (OR). |
| `not` | Inverts a condition (NOT). |

Example:

```json
{
  "operator": "all",
  "conditions": [
    {
      "field": "currency",
      "operator": "==",
      "value": "usd"
    },
    {
      "field": "amount",
      "operator": ">",
      "value": 5000
    }
  ]
}
```

Execution is blocked only if **both** conditions evaluate to `true`.

---

## Comparison Operators

### Equality & Ordering

| Operator |
|----------|
| `==` |
| `!=` |
| `>` |
| `>=` |
| `<` |
| `<=` |

These operators require scalar values.

Example:

```json
{
  "field": "amount",
  "operator": ">",
  "value": 1000
}
```

---

### Membership

| Operator |
|----------|
| `in` |
| `not_in` |

The value must be an array.

```json
{
  "field": "currency",
  "operator": "in",
  "value": [
    "usd",
    "eur"
  ]
}
```

---

### Substring

| Operator |
|----------|
| `contains` |
| `not_contains` |

```json
{
  "field": "email",
  "operator": "contains",
  "value": "@company.com"
}
```

---

### String Matching

| Operator |
|----------|
| `starts_with` |
| `ends_with` |
| `matches` |

Example:

```json
{
  "field": "branch",
  "operator": "starts_with",
  "value": "release/"
}
```

`matches` accepts a regular expression up to **512 characters**.

---

### Presence

These operators do not require a value.

| Operator |
|----------|
| `exists` |
| `not_exists` |
| `empty` |
| `not_empty` |

Example:

```json
{
  "field": "api_key",
  "operator": "exists"
}
```

---

### Time Comparison

Supported operators:

| Operator |
|----------|
| `before` |
| `after` |

Example:

```json
{
  "field": "expires_at",
  "operator": "before",
  "value": "2026-12-31T00:00:00Z"
}
```

---

### Time Windows

Supported operators:

| Operator |
|----------|
| `between` |
| `outside` |

The value must contain exactly two timestamps.

```json
{
  "field": "created_at",
  "operator": "between",
  "value": [
    "2026-01-01T00:00:00Z",
    "2026-12-31T23:59:59Z"
  ]
}
```

---

## Nested Conditions

Complex policies can combine multiple logical operators.

Example:

```json
{
  "when": {
    "operator": "all",
    "conditions": [
      {
        "field": "amount",
        "operator": ">",
        "value": 100000
      },
      {
        "field": "currency",
        "operator": "in",
        "value": [
          "usd",
          "eur"
        ]
      },
      {
        "operator": "not",
        "conditions": [
          {
            "field": "test_mode",
            "operator": "exists"
          }
        ]
      }
    ]
  }
}
```

This policy only matches when:

1. Amount is greater than `100000`
2. Currency is either `usd` or `eur`
3. `test_mode` is **not** present

---

## Best Practices

- Keep policies focused on a single responsibility.
- Use descriptive policy IDs.
- Validate policies after every change.
- Prefer multiple small policies over one complex rule.
- Store policies in version control alongside your project.
- Test policies in sandbox mode before deploying to production.

---

Now that you understand runtime guard policies, continue with:

## Next Steps

- [manifest.json](https://docs.swytchcode.com/configuration/manifest-json/) - Configure endpoints, retries, authentication, and execution behavior.
- [tooling.json](https://docs.swytchcode.com/configuration/tooling-json/) - Learn how Swytchcode defines trusted methods and workflows.
- [Production Guardrails](https://docs.swytchcode.com/policies/production-guardrails/) - Build secure execution policies for production environments.
