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

# Portable proofs

> Move a verified result between apps without repeating the check.

CAIP-380 is an open [ChainAgnostic draft](https://github.com/ChainAgnostic/CAIPs/pull/380). This page describes the portable envelope emitted for wallet-signed NEUS verification requests.

## Scope of the proposal

One wallet-signed envelope; apps validate off-chain; stable **qHash**.

* Networks use CAIP-2 (`eip155:1`, `solana:mainnet`, ...)
* Account ids use CAIP-10 (`eip155:1:0x...`, `solana:mainnet:...`) where an `*AccountId` field is emitted
* Stable profile and proof URLs use W3C `did:pkh` (`did:pkh:eip155:1:0x...`)

## Identity and chain glossary

| Term      | Shape                                 | NEUS usage                                                                                                                                                                                                   |
| --------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| CAIP-2    | `namespace:reference`                 | Network context. Use `chain` for non-EVM signing and account identity, for example `solana:mainnet`.                                                                                                         |
| CAIP-10   | `namespace:reference:account`         | Account id fields such as `agentAccountId` and `controllerAccountId`.                                                                                                                                        |
| `did:pkh` | `did:pkh:namespace:reference:account` | Stable DID for profiles, proof subjects, and `/u/[did]` URLs. It is derived from the same chain and account context, but is not a bare CAIP-10 string.                                                       |
| `chainId` | number                                | EVM-only compatibility field. For signer context it can be omitted by standard EVM integrations because NEUS resolves the hub chain. For asset verifiers, set the verifier-specific `chainId` inside `data`. |

Rule of thumb: EVM browser flows can rely on hosted verify or pass an explicit EVM provider. Non-EVM flows pass the wallet/provider explicitly and include `chain` as a CAIP-2 value.

## NEUS anchor

**`qHash`** (0x…) is SHAKE-256 (256-bit) of the canonical subset `did`, `verifierIds`, `data`, `signedTimestamp`, and exactly one of `chainId` or `chain`. Every field inside `data`, including a nonce or timestamp, remains bound to the hash. [Verification results](../../platform/receipts-and-results)

## Inputs (conceptual)

Account + chain, `verifierIds`, `data` (canonical JSON), `signedTimestamp`, EVM `chainId` or non-EVM `chain` (CAIP-2).

Canonical JSON normalizes strings and keys to NFC, sorts object keys by Unicode code point, preserves array order and `null`, and rejects `undefined`, sparse arrays, non-finite numbers, functions, symbols, and bigint values. An envelope must contain exactly one of `chainId` or `chain`.

## Signer string

Six-line UTF-8, LF. The wallet must sign these exact bytes. **`POST /api/v1/verification/standardize`** returns **`signerString`** for raw HTTP and debugging; the SDK **`verify()`** path builds the same message client-side (or use **`standardizeVerificationRequest`** when you need the API round-trip).

```text theme={"dark"}
Portable Proof Verification Request
Wallet: <address>
Chain: <chainId or CAIP-2 chain>
Verifiers: <comma-separated-ids>
Data: <json payload>
Timestamp: <unix-ms>
```

Same as [Signing format](../../verification/signing-format).

## What the envelope proves

The wallet signature and `qHash` prove the integrity and signer authorization of the request envelope. They do not, by themselves, prove that a particular verifier ran or that NEUS produced a result. A NEUS trust receipt adds verifier results and status around that request anchor.

Session-authorized and service-authorized verification can still produce NEUS trust receipts, but those receipts are not CAIP-380 envelopes because they do not contain a verified wallet signature. Creation responses use `receipt.format: "caip-380-envelope"` only for qualifying envelopes and `receipt.format: "neus-receipt"` otherwise.

## Offline verification

Keep `portableProof` from the verification creation response. NEUS does not persist the complete request envelope by default.

```javascript theme={"dark"}
import { verifyPortableProofEnvelope } from '@neus/sdk';
import envelope from '../../../examples/caip-380/minimal-evm.json' with { type: 'json' };

const result = await verifyPortableProofEnvelope(envelope);
if (!result.valid) throw new Error(result.errors.join('; '));
```

The helper recomputes `qHash`, checks the DID and chain binding, reconstructs the six-line message, and verifies EIP-191 or Ed25519 locally. EIP-1271 smart accounts require chain state; pass an ethers provider as `options.provider`.

Use the [small EVM fixture](https://github.com/neus/network/blob/main/examples/caip-380/minimal-evm.json) for adapter tests. Its timestamp is historical, so `fresh` can be false while its hash and signature remain valid.

## Profiles

|        | Chain      | Signature             |
| ------ | ---------- | --------------------- |
| EVM    | `chainId`  | EIP-191 / 1271 / 6492 |
| Solana | `solana:…` | Ed25519               |
| Other  | CAIP-2     | Profile-specific      |

## Freshness

NEUS rejects a new request if `signedTimestamp` is older than 5 minutes or more than 60 seconds in the future. Historical offline verification reports freshness separately from cryptographic validity.

## Spec

[CAIP-380 (ChainAgnostic)](https://github.com/ChainAgnostic/CAIPs/pull/380)
