# Security Model

FervusAI is designed so that no single party - including FervusAI itself - can unilaterally move funds from an agent wallet. The security model is structural, not policy-dependent.

***

## Non-custodial by design

FervusAI wallets are **Program Derived Addresses (PDAs)**. PDAs have no private key - they are controlled exclusively by the on-chain program that owns them. This means:

* FervusAI does not hold private keys. There are none to hold.
* There is no key management infrastructure that can be breached or compromised.
* FervusAI cannot unilaterally move funds from any wallet without executing a valid, policy-compliant transaction instruction.

The FervusAI on-chain program is the custodian. Its logic is deterministic, auditable, and deployed to Solana Mainnet - operators can review the program's behaviour independently.

***

## Session authority tokens

The off-chain credential that authorises an agent to submit transactions is a **session authority token**. These are short-lived JWTs issued at wallet provisioning time.

Properties:

* **Scoped to a single wallet ID** - a token for `wal_9f3a2b` cannot be used to transact from any other wallet.
* **Short TTL** - default 1 hour, configurable down to 5 minutes.
* **Rotatable** - operators can revoke and reissue session tokens at any time from the dashboard or via `POST /v1/wallets/{wallet_id}/rotate-token`.

Even with a valid session token, a transaction must pass on-chain policy enforcement before it executes. A stolen token grants the ability to *attempt* transactions - not to bypass policy.

***

## MPC co-signing

For transactions at or above the wallet policy's `requireCoSign` threshold, a **2-of-2 MPC signature** is required:

1. **Agent session signature** - the standard session authority token, already required for all transactions.
2. **Operator co-signature** - generated by the operator's key, either via the dashboard approval flow or a programmatic signing endpoint.

The two signatures are combined off-chain before the transaction is submitted. Neither signature alone is sufficient.

This creates a hard checkpoint for high-value movements without adding latency to normal agent operations below the threshold.

### Operator co-signing flow

**Manual (dashboard):**

1. Agent submits a transaction above the co-sign threshold.
2. Transaction enters a `pending_co_sign` state - no on-chain action yet.
3. Operator receives an alert and approves or rejects in the dashboard.
4. On approval, the combined transaction is submitted to Solana.

**Programmatic:**

1. Agent submits a transaction to `POST /v1/payments` with a `requireCoSign` intent.
2. FervusAI returns a `co_sign_payload` - a serialised transaction for the operator to sign.
3. Operator signs the payload using their operator key and returns it to `POST /v1/payments/{tx_id}/co-sign`.
4. FervusAI assembles the final transaction and submits it.

***

## On-chain policy enforcement

All policy rules are enforced by the FervusAI on-chain program - not by API middleware, not by the SDK, and not by any off-chain component. The enforcement sequence for every transaction:

1. Verify the session authority token is valid and scoped to this wallet.
2. Check `maxPerTx` - reject if exceeded.
3. Check `allowedRecipients` - reject if recipient is not whitelisted (when list is non-empty).
4. Check `blockedCategories` - reject if recipient matches a blocked category.
5. Check rolling `maxPerDay` and `maxPerMonth` accumulators - reject if exceeded.
6. Check `velocityCap` - reject if hourly transaction count is exceeded.
7. Check `expiry` - reject if policy has expired.
8. If all checks pass, execute the USDC SPL transfer instruction.

Steps 1–7 happen atomically within a single Solana transaction. If any check fails, the entire instruction is rejected and no state changes.

***

## Wallet isolation

Each wallet is an independent PDA with its own USDC token account. Compromise of one wallet's session token cannot affect any other wallet. There is no shared account state between wallets.

***

## Organisation-level access controls

Within a FervusAI organisation, access is role-based:

| Role       | Permissions                                                                       |
| ---------- | --------------------------------------------------------------------------------- |
| `owner`    | Full access - billing, API keys, all wallets, all policies                        |
| `admin`    | Manage wallets and policies - cannot modify billing or delete the org             |
| `operator` | View wallets, approve co-sign requests - cannot create wallets or modify policies |
| `viewer`   | Read-only access to dashboard and transaction history                             |

API keys are scoped to a role at creation and cannot be escalated.

***

## Responsible disclosure

To report a security vulnerability in FervusAI's on-chain program, API, or dashboard, email **<security@fervus.ai>** with a description of the issue. Do not disclose publicly before coordinating with the team. We target a 72-hour initial response for all security reports.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.fervusai.com/core-concepts/security-model.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
