---
title: "Security Overview"
description: "Defense-in-depth architecture for AIMM protocol security"
audience: tech
type: reference
status: live
lang: en
updated: "2026-09-04"
publish: true
---
# Security overview

The contract-level view of AIMM security: the adversaries the design is built against, the four
layers that answer them, how storage and reentrancy are isolated, and which limitations are
deliberate rather than pending. Authority, who may halt, who may upgrade, and how long each takes,
is [Access Control, Roles & Emergency Powers](/docs/3-1-access-control-roles-emergency-powers).
Disclosure intake is [Bug Bounty](/docs/3-7-bug-bounty). Operational checklists live with their
audience: [Pool Deployment & Curation §7](/docs/5-1-2-pool-deployment-curation#7-checklist) for
deployers and curators, [Providing Liquidity §10](/docs/4-2-providing-liquidity#10-lp-checklist)
for LPs. A taker holds none: the slippage bound, the TTL staleness gate and the coverage toll are
enforced on the swap path by the contracts, and the one caller-supplied input is `minAmountOut`
([Basic Operations](/docs/5-1-1-basic-operations), [Quotes & Routing](/docs/5-2-2-quotes-routing)).

---

## 1. Defense layers

| Layer | Focus |
|-------|-------|
| Economic | External mark, inventory skew bounds, coverage toll |
| Access control | Timelocked governance, asymmetric guardian halt |
| Operational | Asset halt, depeg halt, flow guards |
| Code | Tests, internal review, invariant proofs; third-party audit pending; [§10](#10-audit-status) |

---

## 2. Threat model

### 2.1. Adversary capabilities

| Adversary | Capabilities | Mitigations |
|-----------|--------------|-------------|
| **Flash Loan Attacker** | Unlimited capital for single transaction | No write-on-swap (external mark); volatility-adaptive per-push deviation band |
| **Whale Trader** | Large positions, multi-block attacks | External keeper mark; inventory skew bounds |
| **MEV Searcher** | Ordering, sandwich; oracle-push OEV | Slippage protection; symmetric spread + skewed mid; `minFee`; private keeper relay preferred |
| **Oracle Manipulator** | Compromised keeper; stale push | k-of-n quorum + `revokeSigner`; deviation band; confidence halt; depeg bands |
| **Governance Attacker** | Majority control | Timelocks + grace windows ([Access Control & Roles](/docs/3-1-access-control-roles-emergency-powers)) |
| **Smart Contract Exploiter** | Code bugs | Guardian halt; beacon upgrade is fleet-wide after the `UPGRADE` tier delay with a 7-day grace, cancellable ([Deployment & Upgrades](/docs/3-2-deployment-upgrades)) |

### 2.2. Trust assumptions

Only one principal here can do something destructive. The rest are bounded by what the contracts
let them call, not by an expectation that they behave.

| Principal | Trust level | What it can actually do |
|-----------|-------------|-------------------------|
| **Owner** | Trusted | The one destructive authority. Writes risk parameters, curves, oracle config and hooks, upgrades the fleet, and is the only principal that can un-halt. Upgrades are timelocked; risk params deliberately are not ([3.2 §7.3](/docs/3-2-deployment-upgrades)) |
| **Guardian** | Limited, fail-safe | Halt, tighten, cancel, and nothing else. Cannot un-halt, cannot upgrade, cannot move value. Compromising it degrades the protocol to a stopped state, never a drained one ([3.1 §4](/docs/3-1-access-control-roles-emergency-powers)) |
| **Treasury** | **Not trusted with user funds** | `collectProtocolFees` and nothing else (`Admin.sol:342`): it pulls the protocol's own accrued fee share to itself. It cannot touch reserves, liabilities, LP positions or parameters. A compromised treasury address costs the protocol its fees; it does not put a depositor at risk |
| **Treasury owner** | Trusted, scoped to custody | Rotates the treasury address, through the queue-then-execute timelock. A second governance authority on purpose, so fee custody can sit on a different multisig from the parameter owner, and either can veto a pending rotation |
| **NXR signers** | Verified, k-of-n | The mark's actual authority. A price is accepted because at least `k` of `n` registered signers signed that exact blob, never because of who submitted it |
| **Oracle relayer (keeper)** | Untrusted | `batchPushSigned` takes no sender check (`ExternalOracle.sol:507`), so anyone may submit a validly-signed blob and the keeper holds no signing key. It can delay, withhold or reorder: a liveness actor, not a trust one, and staleness is what the chain gates on |
| **Pool deployer** | Untrusted | `createPool` is permissionless. The deployer's address seasons the CREATE2 salt and confers no authority ([Pool Deployment & Curation §2](/docs/5-1-2-pool-deployment-curation#2-pool-ownership--control)) |
| **Users** | Untrusted | Every input validated at the boundary |

---

## 3. Security layers

### 3.1. Layer 1: economic security

Manipulation resistance:

- **External keeper mark**: quote source is an off-venue aggregate (NX-Rates), not pool reserve state; reserve moves cannot move the quote.
- **No write-on-swap**: a swap never mutates a feed, so there is no accumulator to manipulate.
- **Inventory skew bounds**: `Pricing.computeInventorySkew` returns a dimensionless `int8` clamped to $[-100, 100]$, saturating at coverage $c \le \tfrac12$ and $c \ge 2$. One skew unit maps to $10^4/200 = 50$ bps of curve-x displacement, so the clamp caps the coverage-driven *mid shift* at $\pm 5000$ bps of the curve, then clamps into range. Spline depth and spread are separate terms, so this is not a cap on total price impact. The bounds are fixed in code, not operator-set.
- **Reserve floor**: the per-asset `minLiquidity` is the only hard outflow gate: a swap, withdrawal or flash loan reverts `InsufficientAmount` if it would leave $R_{liq}$ below it (`PoolIOLib.settle`; there is no `exec` function). There is no coverage-ratio drainage floor: coverage prices flow, it never blocks it.

Incentive alignment:

- **Coverage-aware pricing**: the symmetric spread plus inventory-skew mid shift and convex coverage toll make coverage-worsening flow pay more (no directional fee term in the spread itself).
- **LP haircuts**: an exit from an under-covered leg is haircut linearly in the deficit, and the suppression cannot be configured away (`haircutSuppressorBps < 20_000` enforced at the write, `== 0` forced on a coverage-walled leg). It fires at the moment an LP actually leaves, so leaving raises the coverage ratio for those who stay and there is no first-mover advantage. Coverage is never rewritten by a background process.

### 3.2. Layer 2: access control

Four principals, `owner`, `treasuryOwner`, guardians and risk stewards, plus the oracle signer set, with seven timelock tiers from 1 to 14 days under `PROD_DELAYS`. Full principal table, guardian can/cannot matrix, halt authority and the duration schedule:
[Access Control, Roles & Emergency Powers](/docs/3-1-access-control-roles-emergency-powers) (SSoT).

Two properties are worth stating here because they shape everything else:

- **Guardians are fail-closed only**: halt, tighten, cancel; never un-halt, widen, or write params.
- **Risk parameters are deliberately not timelocked**: bounded instead by owner fences plus a relative step clamp ([Deployment & Upgrades §7.3](/docs/3-2-deployment-upgrades#73-risk-parameters-are-deliberately-not-timelocked)).

### 3.3. Layer 3: operational security

Per-asset feature flags (`PoolConstantsLib.sol`):

```solidity
HALT_RISK_BIT              = 1 << 0  // Per-asset risk halt
SWAP_ENABLED_BIT           = 1 << 1  // Swap operations
LIABILITY_SWAP_ENABLED_BIT = 1 << 2  // LP position swaps
FLASH_ENABLED_BIT          = 1 << 4  // Flash loans
HALT_GUARDIAN_BIT          = 1 << 6  // Guardian emergency halt (separate source from risk)
// bits 5 and 7 are reserved; bit 3 is unallocated
HALT_MASK = HALT_RISK_BIT | HALT_GUARDIAN_BIT  // checked at every value-moving gate
```

Halt granularity is per-asset: there is no pool-wide pause bit, and `HALT_MASK` gates `deposit`, `donate`, `withdrawTo` and `swapLiability` as well as swaps. Who may set and clear each bit, and every other untimelocked lever: [Access Control & Roles §4](/docs/3-1-access-control-roles-emergency-powers#4-halt-authority).

The operator-set thresholds are four, and only four:

| Threshold | Bound |
|---|---|
| `minLiquidity` | per-asset reserve floor, the hard outflow gate |
| `haircutSuppressorBps` | how much of an under-covered leg's deficit a same-asset exit is spared; strictly below 20,000, so the haircut can never be disabled |
| `kappaCovBps` | convex coverage-wall strength; 0 disables the wall and is forbidden on every listed asset including the hub |
| `refBandBps` | feed-relative depeg tolerance, mandatory on every non-base leg ([Depeg Halt §2.4](/docs/3-5-depeg-halt#24-per-asset-price-band-depeg-guard-for-spokes)) |

### 3.4. Layer 4: code security

Solidity `=0.8.36` (exact pragma), custom error types, and the build-time artifact guards that pin storage layout (`ArtifactGuards.t.sol`, `AdminFlashUUPS.t.sol`). The test suite covers unit, integration, fuzz and invariant cases; specific proofs are cited at the property they establish rather than claimed in aggregate here.

Third-party audits: **none published**, and no pre-launch external review completed. See [§10](#10-audit-status).

---

## 4. Storage security

### 4.1. Standalone-contract storage isolation

Storage isolation is structural: every contract is standalone with its own default storage layout, and cross-contract calls between distinct singletons (`Admin`↔`Pool`, `Flash`↔`Pool`) are standard external calls, no shared storage, so slot collisions between *different* contracts are impossible by construction. `Pool`'s own internal DELEGATECALL targets, the linked libraries `PoolConfig`, `PoolLiquidity`, `Pricing` and `NUQuartic` (see [AIMM Overview §2.1](/docs/1-overview#21-standalone-singletons--pool-proxies) for the no-Diamond architecture), are a separate case: they take `Pool`'s `$` as a `storage` parameter, so the compiler resolves the slots and there is no hand-mirrored layout to drift.

- Each `Pool` is an ERC-1967 beacon proxy on `PoolFactory` (the factory **is** the beacon) with its own `PoolStorage` at slot 0. Cross-pool storage isolation is automatic; code is shared and swappable fleet-wide.
- The `Admin` and `Flash` singletons are UUPS contracts behind ERC-1967 proxies (`UpgradeGate`, placed first so its 50 reserved slots lead the layout); their state is keyed by `(pool, ...)`.
- The reference `Pool` impl follows an **append-only** rule on `PoolStorage`: existing fields' offsets and types are frozen across upgrades (new fields appended only). `ArtifactGuards.t.sol` pins it at build time, asserting `Pool` declares exactly one storage entry (`$` at slot 0).
- ERC-7201 namespaced storage is **not used** anywhere: plain default storage at slot 0 is sufficient since DELEGATECALL targets are fixed at compile time (no Diamond/module-registry pattern).

### 4.2. Transient storage (EIP-1153)

Transaction-scoped only, cleared automatically at the end of the transaction: reentrancy guards, oracle price caching, flash-loan state.

---

## 5. Reentrancy protection

`Pool` inherits `TransientGuard` (`shared/evm/src/base/TransientGuard.sol`), which overrides Solady's mainnet-only default so TSTORE/TLOAD is forced on every chain, and marks every external entrypoint `nonReentrant`: the mutex slot is Solady's, not a hand-rolled one. A second, slot-isolated transient flag blocks reserve-crediting inflows while a flash callback is in flight. Both guards, the exploit they close and their gas: [Flow Guards](/docs/3-3-flow-guards).

---

## 6. Oracle security

| Attack | Defense |
|--------|---------|
| Flash loan | No write-on-swap (quote source is an external mark, not pool state) |
| Multi-block | Volatility-adaptive per-push deviation band + reference-feed halt, independent where the reference carries a disjoint signer set ([3.6 §4.6](/docs/3-6-oracle-price-push-security#46-independent-reference-the-deploy-disjointness-preflight)) |
| Low liquidity | N/A, price is an external keeper mark, not pool-liquidity-derived |
| Staleness | TTL-based freshness check (fail-closed) + staleness surcharge |

Validation on the push path, all on-chain and all fail-closed:

- **A per-feed TTL revert.**
- **A mandatory per-feed push clamp** (`maxDeviation`, enforced in `_checkDeviation`; `maxDeviation == 0` reverts at `addFeed` and `updateFeed`), volatility-adaptive and hard-capped, so a compromised signer quorum is bounded to a monitorable step per push rather than a one-shot move.
- **A k-of-n distinct-signer quorum per batch.**

Multi-source aggregation happens off-chain in the keeper (NX-Rates); the chain sees a single mark. Formula and terms: [Oracles §8.3](/docs/3-4-oracles#83-deviation-bounds). Quorum ceremony: [3.6 §4](/docs/3-6-oracle-price-push-security#4-the-whitelisting-ceremony).

There is one mode and no fallback switch. Degradation is a ladder of reverts:

| Condition | Effect |
|-----------|--------|
| age past half the TTL | staleness surcharge widens the spread |
| age past the TTL | revert `StaleData` (fail-closed) |
| confidence above `MAX_CONFIDENCE_HALT_BPS` (1,000 bps, strict) | revert `ThresholdViolation` |
| base-token depeg past `BASE_DEPEG_HALT_BPS` | revert `BaseDepegged` (hub halt) |
| spoke mark outside `refBandBps` of its reference | revert `PriceOutsideRefBand` |

Thresholds and readers: [Oracles §8.2](/docs/3-4-oracles#82-staleness-protection), [Depeg Halt §2](/docs/3-5-depeg-halt#2-mechanism).

---

## 7. Upgrade security

Pools are **not** per-instance immutable. Upgrades happen by swapping the implementation on the shared beacon at `PoolFactory`, which re-points every live pool at once, third-party pools included, with no opt-out and no version pinning. `Admin` and `Flash` upgrade separately as UUPS singletons under the same `UPGRADE` tier. Procedure, grace window, cancel authority and the storage-layout obligation: [Deployment & Upgrades §4](/docs/3-2-deployment-upgrades#4-upgrade-mechanisms).

`PoolFactory`, the `LPToken` implementation, `ExternalOracle` and the four linked libraries have **no upgrade path at all**: none sits behind a proxy. Replacing any of them is a redeployment plus a repoint, which for an oracle means a per-asset `UPDATE_ORACLE` op at the `BASE` tier ([Deployment & Upgrades §4.3](/docs/3-2-deployment-upgrades#43-contracts-with-no-upgrade-path)).

---

## 8. Emergency procedures

Runbook and authority: [Access Control, Roles & Emergency Powers §4](/docs/3-1-access-control-roles-emergency-powers#4-halt-authority). Disclosure intake: [Bug Bounty](/docs/3-7-bug-bounty).

---

## 9. Known limitations

### 9.1. Economic bounds

| Limitation | Bound | Implication |
|------------|-------|-------------|
| Max skew | $\pm 100$ (dimensionless) | the skew offset saturates at the band edge; sign only, no separate premium parameter; see [§3.1](#31-layer-1-economic-security) for the mapping to curve bps |
| Anchor depth | `MAX_DEPTH = 4` (enforced, general) | Each asset may anchor to any non-base parent within 4 steps and price against that parent's mark - the tree is general, not fixed at one level. Whether a given pool uses that depth is configuration: there is no feature flag, depth is whatever the `anchor` column says, and a deep edge is one timelocked `UPDATE_ANCHOR` op away once its cross mark exists |
| Max path | $L_{\max} = 2 D_{\max} + 1 = 9$ nodes (8 legs) | Unique tree path via the LCA; only the two endpoints settle. Depth bounds one walk, a path is two |
| Worst-case trade cost | **Not bounded by config, by design.** A spread widened by $\sigma$, confidence or staleness is the honest price of that risk; capping it would sell an underpriced quote and cap the pool's defense exactly when it is most needed. The bound is the caller's `minAmountOut`, exact and per trade | An integrator must quote and enforce, not read a ceiling off config. The uint16 saturation of `SwapQuote.spreadPbps` is a field width, not a policy |

### 9.2. Oracle limitations

The mark is an off-chain aggregate, signed by a $k$-of-$n$ attester set and relayed by an unpermissioned
submitter. That is three places a price can be attacked, and they are not interchangeable: the on-chain
guards answer the second and third well and the first barely at all. Push-path mechanics:
[3.6 §5](/docs/3-6-oracle-price-push-security#5-how-a-push-is-guarded-defense-in-depth).

| Surface | Attacker must control | What the contracts do | Residual |
|---------|-----------------------|-----------------------|----------|
| **1. The source.** The aggregate is computed faithfully; its inputs are not | A majority of the volume-weighted venues behind one NX Rates composite, simultaneously, for at least one push interval | **Nothing that can detect it.** The signature covers a correctly computed aggregate of manipulated inputs, so every check passes by construction. `FeedMathLib.deviationBand` bounds how *fast* the mark may move; `PoolIOLib.priceBandGuard` compares it against a reference built from the same aggregation | The largest of the three. Bounded economically and off-chain, never cryptographically |
| **2. The price provider.** A signed price that existed on no venue | $k$ of $n$ granted attester keys ($k = 2$, $n = 3$ on current deployments), or coercion of the replicas holding them | `NxrSignerSet._verifyQuorum`: $k$ distinct granted signers over one `verifyingContract`-bound EIP-712 digest. Magnitude is then clamped per push by `FeedMathLib.deviationBand`, $\sigma$ is floored at the realized $\lvert\Delta p\rvert/p$, `confidenceBps > MAX_CONFIDENCE_HALT_BPS` (1,000) fails closed, `sourceTs` must strictly advance, and a `sourceTs` more than `SOURCE_TS_FUTURE_SKEW_SECS = 5` ahead is rejected. Guardian `revokeSigner` and `pauseFeed` are immediate | The band caps the step, not the sum. The cumulative bound is the reference band, and it collapses wherever the reference shares the primary's signer set, Arc today |
| **3. The keeper.** Withhold, delay, reorder, submit selectively | The keeper host and its funded EOA. No signing key: push authority comes from the signatures, `msg.sender` is unpermissioned | It cannot forge or edit: the digest commits to the whole blob. Reorder and replay die on the monotonic `sourceTs` (V1 reverts; V2 skips the record; the live V4 steps over the whole slot, silently, and its guard is one accepted write per slot per **source second**, not one per feed per block). Relabeling an old blob as fresh dies on `FeedMathLib.obsAt` $= \min($ attested `sourceTsMs`, landing `updatedAtSecs` $)$ — on V4 those are the same number, and the defense is instead the 6 h `MAX_RECON_AGE` acceptance window, applied on the read side as well. V4 has no `maxRelayLagSecs`. Withholding hits the TTL and fails closed | Withholding is a halt, and a halt is still a win for a griefer. Delay inside the premium-free grace, $\min(\texttt{ttlSecs}/2, 30\,\text{s})$, is free |

**Surface 1 has no cryptographic answer, by construction.** What exists is off-chain and statistical: NX Rates
refuses to sign a composite that carries fewer than `min_accepted_providers` accepted venues (2 on mainnet),
too few genuinely-ticking legs, or a composite uncertainty above its class ceiling (20 bps pegged, 150 bps
volatile); per-source weight is capped at $\mathrm{clamp}(\sqrt{\mathrm{HHI}_\text{winsorized}}, \cdot)$ so no
single venue carries the mark. Every one of those catches a *minority* venue moving: dispersion widens the
composite CI and the quote is refused. A coordinated majority move does the opposite: the legs agree, the CI
stays tight, and the composite is signable and correctly signed. Downstream, the deviation band bounds how
fast that mark can walk the pool and the reference band adds nothing at all, because the reference is built
from the same aggregation. Stated precisely: both bound the *rate of change*, neither bounds *correctness*.
The real defense is the capital cost of moving a majority of the weighted book, plus monitoring, and for a
thin asset that cost is low, which is why listing is a curation decision
([Pool Deployment & Curation §7](/docs/5-1-2-pool-deployment-curation#7-checklist)).

**A stale or off-market price is refused before it is signed, off-chain, not on-chain.** Each NX Rates
replica countersigns a peer-proposed blob only after re-validating every record against its own live market
view:

- **Price** within the feed's `cosign_tolerance_bps` (per-feed, bounded to $[0.01, 5]$ bps).
- **`sourceTs`** skew and age bounds.
- **Agreement** with its own provider-observation timestamp.
- **$\sigma$** within an understatement floor and an overstatement ceiling.
- **Confidence** below the on-chain halt threshold.

Below quorum nothing is served, so
one compromised or lagging replica cannot get a bad price signed. What the chain cannot do is *verify that
this happened*: on-chain, a batch is a valid $k$-of-$n$ signature and a TTL, nothing more. Read the
co-signing check as the defense against a minority compromise, and the guards in surface 2 as the defense
against the quorum itself.

**Where the reference oracle shares the primary's signer set, surface 2's cumulative bound is gone.** One
compromised quorum signs the mark and the reference together, the `refBand` walks in lockstep and never
trips, and only the per-push rate limit and the guardian levers survive. This is a per-chain deploy property,
not a protocol property: verify it by comparing `SignerGranted` logs on the two oracle addresses. Arc shares
a set today
([3.6 §4.6](/docs/3-6-oracle-price-push-security#46-independent-reference-the-deploy-disjointness-preflight)).

**The keeper's lever is choice, not content.** The blob is public and `batchPushSigned` takes its authority
from the signatures, so anyone holding a valid blob can land it: that bounds censorship, not timing. Within
the TTL a relayer still chooses which fresh blob lands and when, and up to the grace window the quote carries
no staleness premium, so a small deliberate delay costs it nothing; that is the same push-ordering OEV a
public mempool grants any observer, and it is why the keeper prefers a private relay ([§2.1](#21-adversary-capabilities)).
There is no on-chain mitigation for it. It is bounded operationally:

- **Leader election** with failover across a configured keeper set.
- **A per-feed staleness alarm** at $\max(2 \cdot \text{heartbeat}, \texttt{ttlSecs}/2)$.
- **A periodic manifest-parity check** against the NX Rates roster.

**Availability is a real limitation, but it is not the manipulation model.** Cadence and outage bound how
*well* the pool tracks the market and when it stops trading; they are not paths to a wrong price.

| Condition | What happens |
|-----------|--------------|
| Low keeper cadence, stale mark | Priced first, then refused: the spread carries a staleness premium growing with $\sigma\sqrt{\tau}$ past a grace of $\min(\texttt{ttlSecs}/2, 30\,\text{s})$, and past the feed's TTL `FeedMathLib.gate` reverts `StaleData`. Shorter TTLs for faster feeds |
| Fast price movement | Wider spreads via $\sigma$. The per-push band widens with the attested $\sqrt{\Delta t}$, so a genuine gap move ladders in rather than wedging the feed; past the $10\,d_{max}$ ceiling it does wedge, and the release is the owner's timelocked `requestFeedWiden` → `executeFeedWiden`, shipping in the next release; until then, an oracle redeploy plus a `BASE`-tier `UPDATE_ORACLE` repoint per leg ([3.6 §5.1](/docs/3-6-oracle-price-push-security#51-per-push-band-vs-cumulative-band)) |
| Keeper or feed outage | Fail-closed: swaps revert past TTL, halt beating bleed. Multi-venue aggregation removes the single-venue outage, not the single-provider one |
| Reference feed parked | Every armed spoke band fails closed once the reference passes its own TTL, so the reference must be relayed on the same discipline as the primary |

---

## 10. Audit status

Third-party audit is pending. Until those reports are published, treat the contracts as experimental: the assurance behind them today is the internal review, the test suite and the invariant proofs described on this page, not an independent opinion. Reports will be linked here when they land; there is no placeholder page in the meantime. See [Risk Disclaimer](/docs/risk-disclaimer).

---

## 11. Related documentation

| Page | Role |
|------|------|
| [Access Control, Roles & Emergency Powers](/docs/3-1-access-control-roles-emergency-powers) | Principals, guardian surface, halt authority, timelock table (SSoT) |
| [Bug Bounty](/docs/3-7-bug-bounty) | Disclosure intake |
| [Deployment & Upgrades](/docs/3-2-deployment-upgrades) | Beacon + UUPS |
| [Flow Guards](/docs/3-3-flow-guards) | Reentrancy + deposit→withdraw cooldown |
| [Oracles](/docs/3-4-oracles) | External mark, TTL, bands |
| [Depeg Halt](/docs/3-5-depeg-halt) | Base + spoke circuit breakers |
| [Oracle Price-Push](/docs/3-6-oracle-price-push-security) | Signer quorum, push guards |
| [Observability](/docs/3-8-observability) | Health metrics, tradableRatio, ingest gates |
| [Guardian Operations](/docs/3-9-guardian-operations) | Runbook for the guardian key: levers, argument traps, escalation |
| [Oracle Keeper Operations](/docs/3-10-oracle-keeper-operations) | Runbook for the push relay: triggers, cadence, revert taxonomy |
| [Risk Steward Operations](/docs/3-11-risk-steward-operations) | Runbook for the fenced param lane: clamps, fences, what fails closed |
| [Admin](/docs/1-2-3-admin) | Per-pool admin ops |
| [Risk Disclaimer](/docs/risk-disclaimer) | Legal risk surface |
