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

# Compliance

> Off-chain screening, on-chain attestation, contract-enforced gate.

KeyStone enforces compliance at settlement time. Compliance is the only step that requires KeyStone's off-chain involvement - everything after compliance is handled autonomously by the contracts.

## Three-layer architecture

### 1. Off-chain screening

KeyStone's compliance oracle screens parties via external APIs:

**LSEG World-Check** - Entity-level screening against 100M+ records across 240+ countries:

* Sanctions lists (OFAC, EU, UN, HMT)
* Politically Exposed Persons (PEPs)
* Adverse media
* Enforcement actions

**CipherOwl** - Wallet-level risk scoring across 50+ blockchains:

* Sanctions exposure
* Mixer/tumbler interaction
* Fraud and scam associations
* Protocol risk attribution

### 2. On-chain attestation

After screening, the Pass result is attested to the ComplianceRegistry smart contract via an M-of-N bundle of independent EIP-712 attester signatures:

```
attest(Attestation{settlementId, partyHash, status, referenceHash, deadline}, signatures[])
```

The contract recovers each signer and requires a threshold of distinct attesters before recording the attestation - the submitter is not trusted, the signatures authorize. No personal data is stored on-chain: only the hashed party identifier, the status, and a hashed reference.

### 3. Contract-enforced gate

The KeystoneSettlement contract checks `areAllPartiesCleared(settlementId, partyHashes)` on the ComplianceRegistry before executing - every party hash bound at registration must be attested Pass. No one can skip compliance: the contract enforces it at the moment funds move.

## How it works in a settlement

```mermaid theme={null}
%%{init: {'theme': 'base', 'themeVariables': {'actorBkg': '#1a3a35', 'actorBorder': '#2DD4A8', 'actorTextColor': '#e0f2ef', 'actorLineColor': '#2DD4A8', 'signalColor': '#2DD4A8', 'signalTextColor': '#e0f2ef', 'noteBkgColor': '#162e2a', 'noteTextColor': '#e0f2ef', 'noteBorderColor': '#1AAF8B', 'activationBkgColor': '#1a3a35', 'activationBorderColor': '#2DD4A8', 'labelBoxBkgColor': '#1a3a35', 'labelBoxBorderColor': '#2DD4A8', 'labelTextColor': '#e0f2ef', 'loopTextColor': '#2DD4A8'}}}%%
sequenceDiagram
    participant Oracle as Compliance Oracle (off-chain)
    participant LSEG as LSEG World-Check
    participant CO as CipherOwl
    participant CR as ComplianceRegistry (on-chain)
    participant K as KeystoneSettlement

    Oracle->>LSEG: Screen entity
    LSEG-->>Oracle: PASS
    Oracle->>CO: Screen wallet
    CO-->>Oracle: PASS

    Oracle->>CR: attest(Attestation{...PASS...}, M-of-N signatures)

    Note over K: last deposit lands (or execute() is called)
    K->>CR: areAllPartiesCleared(settlementId, partyHashes)
    CR-->>K: true
    K->>K: execute - pay out every leg atomically
```

## Manual compliance decisions

When a party is flagged, a compliance officer reviews the screening details in the [KeyStone Dashboard](https://app.keystoneos.xyz) and submits a decision. Decisions can also be submitted via the API:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.keystoneos.xyz/v1/settlements/$ID/compliance-decision \
    -H "Authorization: Bearer $TOKEN" \
    -d '{"decision": "approve"}'
  ```

  ```typescript TypeScript SDK theme={null}
  const settlement = await client.compliance.approve("550e8400-...");
  // Or to reject:
  // const settlement = await client.compliance.reject("550e8400-...");
  ```

  ```python Python SDK theme={null}
  settlement = await client.compliance.approve("550e8400-...")
  # Or to reject:
  # settlement = await client.compliance.reject("550e8400-...")
  ```
</CodeGroup>

Decisions are:

* `approve` - Override the flag, allow the settlement to proceed
* `reject` - End the settlement: it transitions to `REJECTED` (nothing was deposited yet)

Both decisions are recorded in the settlement's event history with full audit context.

## Compliance data on the API

Each party's compliance check is exposed on the settlement resource with:

* `status` - `PASS`, `FLAGGED`, or `FAIL` per screening
* `chain_attested_at` - when the on-chain M-of-N attestation landed in the ComplianceRegistry (`null` until it does). Use this to distinguish "screened off-chain" from "attested on-chain and able to execute".

Admin views additionally expose `principal_id`, linking the check to the screened principal's full audit trail.

## Open attestation interface

KeyStone operates the default compliance oracle, but the attestation interface is open:

* **M-of-N attesters**: A Pass is recorded only when a threshold of distinct, independent attesters each sign the same attestation - no single key can forge a Pass. The attester set and threshold are fixed at the registry's deployment.
* **Platform-operated oracles**: Platforms can run their own compliance screening; on-chain enforcement is the standardized threshold gate
* **Verifiable**: All attestations are permanent on-chain records - a false attestation is provable liability

This design separates screening (off-chain, provider-specific) from enforcement (on-chain, standardized gate check).

## What KeyStone stores

<Warning>
  KeyStone never stores raw KYC/AML data. We store only compliance **status** (pass/fail/flagged) and a **reference ID** pointing to the compliance provider's record.
</Warning>

| Layer                         | What is stored                                                 |
| ----------------------------- | -------------------------------------------------------------- |
| Off-chain (KeyStone DB)       | Compliance status + reference ID pointing to provider's record |
| On-chain (ComplianceRegistry) | Hashed party identifier + status enum + hashed reference ID    |

The compliance provider (LSEG, CipherOwl) remains the source of truth for the actual screening data. KeyStone only records the outcome.

## Screening performance

| Metric                  | Value                                                                                                                                    |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| Average screening time  | 2-4 seconds                                                                                                                              |
| Auto-pass rate          | \~95%                                                                                                                                    |
| Supported jurisdictions | 240+ countries                                                                                                                           |
| Re-screening            | Every settlement - screening results are never cached (a daily per-platform cache holds LSEG case-template and resolution metadata only) |

See [ComplianceRegistry](/smart-contracts/compliance-registry) for full contract documentation.
