AURA

Policy Engine

All 27 ViolationCode variants, full evaluation order, public precheck behavior, and PolicyConfig defaults from the actual aura-policy source.

aura-policy is a pure-Rust crate with no Anchor dependency. It is consumed by aura-core on-chain, by sdk-rs for off-chain pre-validation, and by the devnet smoke binaries. All rule logic, violation codes, and FHE graph specs live here — never duplicated in aura-core or the SDKs.

Entry Points

FunctionUsed byWhat it skips
evaluate_transactionPublic proposals (propose_transaction)Nothing — runs all rules
evaluate_public_precheckConfidential proposals (before FHE CPI)Per-transaction, daily, weekly, monthly, and recipient cap checks
evaluate_transaction_simpleTests and off-chain toolingConvenience wrapper
evaluate_batchpropose_batch instructionEvaluates a slice, threads state forward
evaluate_policy_without_spend_mutationsimulate_policy instructionRuns full rules but does not commit state

Evaluation Order (evaluate_transaction)

Rules short-circuit on the first failure. No subsequent rules are evaluated after a violation.

This is the full aura-policy in-crate order. aura-core instructions may also apply sidecar checks around it, such as queue capacity, operator/session authority, dWallet reservations, liveness, exposure groups, timelocks, and settlement state.

Public Precheck vs Full Evaluation

For confidential proposals, evaluate_public_precheck runs the public subset before the Encrypt CPI. Current source evaluates scoped pauses, budget envelopes, Bitcoin manual-review threshold, time window, protocol allowlist, slippage, quote freshness, counterparty risk, shared pool, velocity, and approval ladder. It skips the direct per-transaction, daily, weekly, monthly, and recipient cap checks. The trace explicitly records "encrypted per-transaction and daily-limit checks deferred to Encrypt" before the FHE branch handles the encrypted spend guardrails.

All 27 ViolationCodes

From programs/aura-policy/src/violations/mod.rs:

CodeVariantTriggered when
noneNoneTransaction approved
per_transaction_limitPerTransactionLimitamount_usd > per_tx_limit_usd
daily_limitDailyLimitspent_today + amount > effective_daily_limit
bitcoin_manual_reviewBitcoinManualReviewBitcoin tx above bitcoin_manual_review_threshold_usd
time_window_limitTimeWindowLimitHourly spend would exceed active hourly limit
velocity_limitVelocityLimitRecent-amounts window sum would exceed velocity_limit_usd
protocol_not_allowedProtocolNotAllowedProtocol ID bit not set in allowed_protocol_bitmap
slippage_exceededSlippageExceededComputed slippage > max_slippage_bps
quote_staleQuoteStalequote_age_secs > max_quote_age_secs
counterparty_riskCounterpartyRiskRisk score > max_counterparty_risk_score
shared_pool_limitSharedPoolLimitSwarm pool projected spend > shared_pool_limit_usd
weekly_limitWeeklyLimit7-day total would exceed weekly_limit_usd
monthly_limitMonthlyLimit30-day total would exceed monthly_limit_usd
recipient_daily_limitRecipientDailyLimitPer-address daily cap exceeded
recipient_per_transaction_limitRecipientPerTransactionLimitPer-address per-tx cap exceeded
anomaly_detectedAnomalyDetectedZ-score outlier with action = Deny
cooldown_not_elapsedCooldownNotElapsedCooldown rule blocked a large transaction
budget_envelope_daily_limitBudgetEnvelopeDailyLimitScoped envelope daily cap exceeded
budget_envelope_weekly_limitBudgetEnvelopeWeeklyLimitScoped envelope weekly cap exceeded
approval_ladder_deniedApprovalLadderDeniedApproval ladder returned ApprovalLevel::Deny
execution_scope_pausedExecutionScopePausedTransaction matches an active ScopedPauseEntry
external_dependency_staleExternalDependencyStaleRequired liveness record is stale
policy_attestation_missingPolicyAttestationMissingAttestation missing or stale
empty_batchEmptyBatchBatch proposal contained no items
batch_too_largeBatchTooLargeBatch exceeded maximum item count
exposure_group_limit_exceededExposureGroupLimitExceededCross-treasury exposure group cap exceeded
pending_execution_timelock_activePendingExecutionTimelockActiveExecution timelock still active

PolicyConfig Defaults

From programs/aura-policy/src/config/limits.rsPolicyConfig::default():

FieldDefaultDescription
daily_limit_usd10_000USD cents — 24h rolling window
per_tx_limit_usd1_000USD cents — single transaction cap
daytime_hourly_limit_usd2_500USD cents — 06:00–22:00 UTC
nighttime_hourly_limit_usd500USD cents — 22:00–06:00 UTC
velocity_limit_usd5_000USD cents — recent-amounts window
allowed_protocol_bitmap0b1_1111 (31)All 5 protocol bits set
max_slippage_bps1001%
max_quote_age_secsSome(300)5 minutes
max_counterparty_risk_scoreSome(70)0–100 scale
bitcoin_manual_review_threshold_usd5_000USD cents = $50
shared_pool_limit_usdNoneDisabled
weekly_limit_usdNoneDisabled
monthly_limit_usdNoneDisabled
recipient_limits[]No per-address caps
cooldown_configNoneDisabled
anomaly_configNoneDisabled
budget_envelopes[]No scoped envelopes
approval_ladderNoneDisabled
scoped_pauseemptyNo pauses
liveness_configall falseNo freshness requirements

Reputation Scaling

effective_daily_limit_usd is computed as:

effective = daily_limit_usd × multiplier_bps(reputation_score) / 10_000

Default ReputationPolicy:

ThresholdMultiplier
score ≥ high_score_threshold (80)high_multiplier_bps / 10_000 = 1.5×
score ≥ medium_score_threshold (50)1.0× (baseline)
score < 50low_multiplier_bps / 10_000 = 0.7×

If no reputation score is provided (None), the base daily_limit_usd is used unchanged.

Time Windows

active_hourly_limit returns daytime_hourly_limit_usd for hours 6–21 UTC and nighttime_hourly_limit_usd for hours 22–5 UTC. The hourly counter (hourly_spent_usd) resets when the current hour changes.

Transaction Types

From programs/aura-policy/src/types/transaction.rs:

IDVariantDisplay
0Transfertransfer
1DeFiSwapdefi_swap
2LendingDepositlending_deposit
3NFTPurchasenft_purchase
4ContractInteractioncontract_interaction

Regulatory Flags

compute_regulatory_flags returns a u8 bitmask attached to every PolicyDecision:

BitConstantMeaning
0b0000_0001REG_FLAG_CTR_THRESHOLDAmount exceeds CTR reporting threshold
0b0000_0010REG_FLAG_CROSS_BORDERCross-chain transaction
0b0000_0100REG_FLAG_HIGH_RISK_COUNTERPARTYRisk score above 80
0b0000_1000REG_FLAG_REQUIRES_KYCTransaction type requires KYC

Anomaly Detection

When anomaly_config.enabled = true and state.recent_amounts.len() >= min_sample_size, the engine computes a z-score over the recent amounts window:

z_score_bps = (amount - mean) / std_dev × 10_000

If z_score_bps > z_score_threshold_bps, the action is applied:

AnomalyActionEffect
DenyReturns ViolationCode::AnomalyDetected
FlagForReviewSets risk_score = max(risk_score, 85), adds risk factor, continues
RequireGuardianCosignRequires guardian approval before execution

Policy Templates & Canary Testing

AURA now supports reusable policy templates and safe testing of policy changes through canary deployments.

Policy Templates

Pre-defined or custom policy configurations that can be applied to multiple treasuries:

import { instructions } from "@aura-protocol/sdk-ts";

// Create from scratch or fork a built-in preset
await instructions.policy.sendCreatePolicyTemplate(
  client,
  owner,
  createTemplateInput,
);

// Apply to treasury
await instructions.policy.sendApplyPolicyTemplate(client, owner, applyTemplateInput);

// Apply with parameterized scaling
await instructions.policy.sendApplyPolicyTemplateParameterized(
  client,
  owner,
  applyTemplateParameterizedInput,
);

Built-in presets:

  • ConservativeDao
  • AiAgentOps
  • HighTrustExecutor
  • StrictCompliance
  • IntegrationTestFastPath
  • TradingDesk
  • PayrollSweep
  • GrantDisbursement
  • MevSearcher
  • TreasuryColdStorage

Canary Deployments

Test a candidate policy against live proposals without enforcing it:

import { instructions } from "@aura-protocol/sdk-ts";

// 1. Start canary with candidate policy
await instructions.policy.sendStartCanary(client, owner, startCanaryInput);

// 2. Proposals evaluated against both enforced and candidate policies
// Canary tracks: pass/fail counts, deviation patterns, violation distribution

// 3. Promote if canary performs well
await instructions.policy.sendPromoteCanary(client, owner, promoteCanaryInput);

// Or discard if results are poor
await instructions.policy.sendDiscardCanary(client, owner, discardCanaryInput);

Canary scoring:

  • Runs in parallel with enforced policy (never blocks proposals)
  • Tracks samples, agreements, candidate allow/deny counts, and a per-rule divergence bitmap
  • sample_cap bounds the shadow-evaluation cost and must be reached before promotion when non-zero
  • Automatically records as new policy version on promotion

Policy Versioning & Rollback

All policy changes create immutable version records:

import { accounts, instructions } from "@aura-protocol/sdk-ts";

// Check version history
const history = await accounts.fetchPolicyHistoryAccount(client, policyHistoryPda);
console.log("Version count:", history.versionCount);
console.log("Snapshots:", history.snapshots);

// Roll back by supplying the full candidate config for the target snapshot.
await instructions.policy.sendRollbackPolicy(client, owner, rollbackPolicyInput);

Version lifecycle:

  • Template applies, canary promotion, explicit snapshots, and rollbacks record policy versions in the history ring
  • Versions are sequentially numbered and immutable
  • Rollback is owner-gated; loosening rollbacks are staged through the config-change timelock
  • Version metadata includes timestamp, author, and policy hash/provenance

On this page