> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dfns.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Governance architecture

> How DFNS combines authentication, permissions, policies, and MPC signing into a layered governance model for secure wallet operations.

This page explains how DFNS' governance layers work together to secure your digital assets.

## Overview

Every DFNS API request passes through multiple security layers before a blockchain transaction is signed:

```mermaid theme={null}
flowchart TB
    App[Your Application]

    subgraph Auth[1: Authentication]
        AuthCheck["Verify API token<br/>Verify user action signature"]
    end

    subgraph Authz[2: Authorization]
        PermCheck["Check user permissions<br/>e.g., Wallets:Sign"]
    end

    subgraph Policy[3: Policy Engine]
        PolicyEval["Evaluate matching policies"]
    end

    Blocked([Blocked])
    ApprovalRequired["Approval Required"]
    HumanApproval{"Human Review"}
    Rejected([Rejected])
    Approved["Approved"]

    subgraph MPC[4: MPC Signing]
        MPCSign["Distributed key shares<br/>sign collaboratively"]
    end

    subgraph Broadcast[5: Broadcast]
        BroadcastTx["Send to blockchain"]
    end

    App --> Auth
    Auth --> Authz
    Authz --> Policy
    Policy --> Blocked
    Policy --> ApprovalRequired
    Policy --> MPC
    ApprovalRequired --> HumanApproval
    HumanApproval -->|Reject| Rejected
    HumanApproval -->|Approve| Approved
    Approved --> MPC
    MPC --> Broadcast
```

## Layer 1: Authentication

Every API request must prove identity through two mechanisms:

### API Token

The `Authorization: Bearer <token>` header identifies who is making the request:

* **User tokens**: Short-lived, obtained through login flow
* **Service account tokens**: Long-lived, for server-to-server communication
* **Personal access tokens**: Long-lived user tokens for development

### User Action Signature

For state-changing operations (POST, PUT, DELETE), the `X-DFNS-USERACTION` header proves the caller controls a registered credential:

1. Client requests a challenge from DFNS
2. Client signs the challenge with their credential (passkey or asymmetric key)
3. DFNS verifies the signature matches a registered credential

This ensures that even if a token is stolen, an attacker cannot perform sensitive operations without the credential.

The challenge  you sign binds the exact request you are authorizing: a hash of the request body, the HTTP method, the path, and a server-generated human-readable summary of the action (for example, "Transfer Native asset to recipient 0x..."). DFNS recomputes and re-verifies these when you submit the signed action, so a request that no longer matches what was signed (different recipient, amount, path, or method) is rejected. Your signature is bound to a specific intent, not just to "some request."

## Layer 2: Authorization (Permissions)

After authentication, DFNS checks if the user has permission to perform the requested action.

Permissions follow a whitelist model - users can only perform actions explicitly granted:

```mermaid theme={null}
flowchart LR
    User --> Permission --> Operations
```

Example: A user with `Wallets:Read` can view wallets but cannot transfer assets (requires `Wallets:Sign`).

See [Permissions](/core-concepts/roles-and-permissions) for the full list.

## Layer 3: Policy Engine

Even with valid authentication and permissions, the Policy Engine can add additional controls:

| Policy action     | Effect                                                   |
| ----------------- | -------------------------------------------------------- |
| `Block`           | Transaction is rejected                                  |
| `RequestApproval` | Transaction held until humans approve                    |
| `NoAction`        | Transaction proceeds (used with Chainalysis for logging) |

Policies evaluate rules like:

* Transaction amount limits
* Velocity limits (amount or count over time)
* Recipient whitelisting
* Chainalysis screening

**Important:** All matching policies are evaluated for every activity. If multiple policies apply:

* Any `Block` result immediately blocks the activity
* Multiple `RequestApproval` results require approvals from all triggered policies
* Policies cannot bypass or override each other

See [Policies](/core-concepts/policies) for details.

## Layer 4: MPC Signing

Once a transaction passes all checks, the MPC signing ceremony begins:

```mermaid theme={null}
flowchart TB
    subgraph MPC["DFNS MPC Network"]
        direction TB
        subgraph Signers[" "]
            direction LR
            S1["Signer Node<br/>Share 1"]
            S2["Signer Node<br/>Share 2"]
            S3["Signer Node<br/>Share 3"]
            S4["Signer Node<br/>Share 4"]
        end
        Threshold["Threshold Signature<br/>(k-of-n nodes collaborate)"]
        S1 --> Threshold
        S2 --> Threshold
        S3 --> Threshold
        S4 --> Threshold
    end
```

Key properties:

* **No complete key**: The private key never exists in one place
* **Threshold security**: Requires k-of-n shares to sign (not all shares needed)
* **Geographic distribution**: Nodes are in different data centers/regions
* **Audit trail**: Every signing ceremony is logged

## Layer 5: Broadcast

The signed transaction is broadcast to the blockchain network. DFNS monitors for confirmation and updates transaction status.

## Security model summary

| Layer               | What it protects against                                       |
| ------------------- | -------------------------------------------------------------- |
| Authentication      | Unauthorized access                                            |
| User action signing | Token theft, replay attacks, tampering with the signed request |
| Permissions         | Privilege escalation                                           |
| Policies            | Unauthorized transactions, fraud                               |
| MPC                 | Key theft, single point of compromise                          |

## Separation of concerns

A critical security property: **credentials and keys are completely separate**.

| Credential (Authentication)                                 | Key (Signing)                 |
| ----------------------------------------------------------- | ----------------------------- |
| Proves identity                                             | Signs transactions            |
| Stored on user device (passkey) or server (service account) | Stored in MPC network         |
| Can be revoked/rotated                                      | Key shares are immutable      |
| Compromised credential ≠ stolen assets                      | Protected by all layers above |

Even if an attacker steals credentials, they still face:

* User action signing requirements
* Permission checks
* Policy enforcement
* MPC threshold requirements

## Trust boundaries

The layers above describe how a single request is authorized. This section describes who you have to trust, and how to verify operations independently of that trust.

DFNS operates as the **maker**: it builds the transaction from your request and submits it to the signers. You can operate as the **checker**: you independently verify what is about to be signed, and approve or reject it. A checker step lets you detect a tampered transaction in both directions:

* **If DFNS were compromised**, your checker sees a transaction that does not match the intent you authorized, and rejects it.
* **If your initiating workstation were compromised**, the transaction is checked again before signing, so tampering is caught even though it originated on your own machine.

This is distinct from separation of duties *within* your organization, where the initiator and the approver are different members of your team (see [govern wallet access](/solutions/govern-wallet-access)). Trust boundaries are about verifying DFNS and your own endpoints, not only your team members.

DFNS gives you two places to insert a checker:

| Checker                                                        | When it runs                                    | What it is                                                                                                                                                                                                                                                     |
| :------------------------------------------------------------- | :---------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Policy approval](/core-concepts/policies)                     | Asynchronous: after the request, before signing | A policy with `RequestApproval` holds the operation and notifies an approver with the transaction details. The approver is a human reviewing on a separate device, or a service account running your own automated checks. They approve or reject out of band. |
| [Validation gate](/advanced/deployment-models/validation-gate) | Synchronous: immediately before signing         | Self-hosted signers call an HTTP handler you control before signing, passing a digest of the payload to be signed plus key details. Return `200 OK` to allow, anything else to reject.                                                                         |

### Threat model

Each row assumes the worst case at one location and shows which checker catches a tampered transaction.

| Assume compromised                     | Example                                                        | What catches it                                                                                                                                                                                                                                                                                                                                                  |
| :------------------------------------- | :------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Your workstation, browser, or local UI | The UI shows "send 1 BTC to B" but submits "send 1 BTC to X"   | DFNS builds the transaction from the request it received. A policy approver reviewing on a separate device sees recipient X and rejects. A validation gate handler can compare the signing request against the transaction your systems expect and reject the mismatch. A [trusted display](#trusted-display-wysiwys) lets the operator catch X at signing time. |
| DFNS                                   | You authorize "send to B" but DFNS builds "send to X"          | A checker running on your own infrastructure detects that the transaction does not match the intent you authorized, and rejects it before or at signing.                                                                                                                                                                                                         |
| Your own checker infrastructure        | Your validation gate handler and approver are both compromised | DFNS is healthy and builds the transaction faithfully from the intent you authorized, so "send to B" stays "send to B".                                                                                                                                                                                                                                          |

No single party, whether DFNS, your workstation, or your checker, can unilaterally produce a malicious signed transaction without another layer detecting it.

### Trusted display (WYSIWYS)

The human-readable summary bound into the [user action signature](/api-reference/auth/signing-flows) is what makes "what you see is what you sign" (WYSIWYS) possible: the operator signs a description of the action, not an opaque blob. For this to defend against a compromised client, the summary must be shown to the operator on a surface that the client's own code cannot alter. The standards for this in the browser, such as Secure Payment Confirmation, are still emerging and support is currently limited.

## Related

<CardGroup cols={2}>
  <Card title="How MPC works" icon="lock" href="/core-concepts/how-mpc-wallets-work">
    Deep dive into MPC technology
  </Card>

  <Card title="Policies" icon="shield" href="/core-concepts/policies">
    Configuring transaction policies
  </Card>

  <Card title="Permissions" icon="user-shield" href="/core-concepts/roles-and-permissions">
    Understanding permission model
  </Card>

  <Card title="Authentication" icon="key" href="/api-reference/auth">
    Authentication flows
  </Card>
</CardGroup>
