Skip to main contentPASS
Read the docs

Primitives

Policies

The rule categories a mandate is assembled from, and the difference between core enforcement and optional extensions.

A policy is the smallest unit of machine-enforceable authority in PASS. Each states one condition over a proposed execution and the reason it gives when that condition fails: which assets may be touched, which actions taken, how much value may move in one instruction, which credential must be present. A mandate is not one permission flag. It is an assembled set of policies bound to an actor and a subject, every applicable member of which is evaluated during preflight before an instruction may proceed.

Authority is not a single boolean. An actor may be entitled to trade a tokenized equity and not to bridge it, to move $2,000 and not $5,000, to act today and not next quarter. Collapsing those into one flag loses the distinctions and, with them, the ability to report which was violated.

Policies are declarative, and they operate on an Execution Intent, the normalized description an adapter derives from a raw call. Policies do not read calldata. A rule that parses raw bytes inherits every ambiguity of the encoding, and the same byte string can describe different economic outcomes depending on where it is sent. Adapter first, policy second.

Core policy categories

The core categories form the base vocabulary of the architecture. A conforming preflight implementation evaluates all of them, and a mandate that omits one is incomplete rather than permissive.

Actor binding

Constrains which actor may invoke the mandate at all. The binding between the named actor and the named subject is a rule, not metadata: an instruction submitted by any other key is refused with ACTOR_NOT_AUTHORIZED before the mandate's terms are read. A key that can sign has control of an account; only a mandate that names it carries authority to act for a subject. Where several actors are named, removing one leaves every other term intact.

Asset permissions

Constrains which instruments an intent may reference. The rule is an allowlist, not a denylist, and the choice is structural: a denylist admits every asset that did not exist when the mandate was written, inverting the property a mandate is meant to provide. Evaluation covers every asset the intent touches — a swap references at least two, and both must be enumerated. Failure produces ASSET_NOT_ALLOWED.

In the running example, the mandate held by actor 0x81...29F enumerates AAPL and NVDA, so an intent referencing any third asset is refused here regardless of size, venue or credential state.

Action permissions

Constrains the operation class the intent represents: buy, sell, transfer, bridge, approve. The adapter normalizes a call into exactly one action, and policy is evaluated against that value. Approval deserves treatment as an action in its own right, because it moves no value when granted while delegating the ability to move value later. A mandate that constrains transfers but ignores approvals has a gap. Failure produces ACTION_NOT_ALLOWED.

The example mandate blocks bridging. A bridge call carrying NVDA, an allowed asset, is refused by the action rule rather than the asset rule, and the Reason Code says so.

Venue and adapter permissions

Constrains where execution may occur, expressed as the set of adapters the mandate accepts. Two failures are distinguishable here and should not be merged. If no adapter recognizes the target, no Execution Intent exists and preflight refuses with INVALID_EXECUTION_CONTEXT: the system cannot describe what is proposed, so it cannot authorize it. If an adapter decodes the call but the mandate does not list that adapter, the intent is understood and still not permitted, which is ADAPTER_NOT_ALLOWED. The first is a limit of comprehension; the second is a decision.

Transaction limits

Constrains the value of a single intent. Evaluation is stateless — it needs the intent and a price input, nothing else — which makes this the cheapest of the value rules to compute. Failure produces TX_LIMIT_EXCEEDED.

A per-transaction ceiling alone does not bound exposure. Take the example ceiling of $2,500 with no periodic rule beside it: ten sequential instructions of $2,400 each satisfy the transaction limit while moving $24,000 in aggregate. The running example does carry a periodic rule, so the sequence terminates. Four instructions accumulate $9,600 against a $10,000 window; the fifth would carry the total to $12,000 and is refused with DAILY_LIMIT_EXCEEDED.

Periodic exposure limits

Constrains aggregate value across a defined window, typically a day. Evaluation is stateful: it requires an accumulator keyed by mandate and window. Failure produces DAILY_LIMIT_EXCEEDED.

Two properties must be fixed in the mandate rather than left to the implementation. The first is the window definition: a rolling twenty-four hours and a calendar day disagree at a stated boundary, and the same instruction can be authorized under one reading and refused under the other. The second is the accumulation point. The counter advances on execution, not on evaluation, so a refused or reverted execution does not quietly reduce remaining authority.

Credential requirements

Constrains the attestations that must be present in the Subject's passport and valid at evaluation time. Three failures are distinguished because three remedies follow. MISSING_CREDENTIAL means the credential was never issued or the wrong passport is bound. CREDENTIAL_EXPIRED means it existed and needs renewal. CREDENTIAL_REVOKED means an issuer withdrew it, which is terminal until reissued.

A credential policy asserts a predicate about a credential, not a demand to inspect the personal data behind it. The architecture supports privacy-preserving credential models and external attestations on this basis: preflight needs to know that STOCK_TOKEN_ELIGIBLE holds, not why the issuer concluded it. Passport 0x7F...94A carries that credential alongside IDENTITY_VERIFIED, NON_US_PERSON, EEA_ELIGIBLE and AML_CHECKED.

Temporal validity

Constrains when the mandate may be used at all, through a validity window with a start and an end. Authority that never expires accumulates quietly; a bounded window makes a forgotten mandate self-limiting. Failure produces MANDATE_EXPIRED, covering both a window that has closed and one that has not yet opened.

The time source must be the clock the execution environment itself uses. Evaluating against an offchain timestamp while execution settles against a block timestamp opens a narrow interval in which the two disagree, and near a boundary that disagreement is the whole decision.

Evaluation semantics

Three properties govern how a policy set is evaluated, each a requirement rather than an implementation preference.

All applicable rules must pass. The decision is AUTHORIZED only when every applicable policy passes. Policies do not vote, score or offset one another, and a strong credential position does not compensate for an exceeded limit.

Evaluation is deterministic. The same intent, mandate, passport state, window state and price input produce the same decision and the same Reason Code every time. There is no randomness, no discretion, and no fallback that permits execution when a rule cannot be evaluated. Preflight refuses an intent it cannot validate.

Evaluation order is defined. Because the first failing rule determines the Reason Code, an undefined order would make the reported reason an artefact of implementation rather than a property of the specification.

EXECUTION INTENT
        |
        v
CONTEXT VALID?         -> INVALID_EXECUTION_CONTEXT
        |
        v
ACTOR BOUND?           -> ACTOR_NOT_AUTHORIZED
        |
        v
MANDATE ACTIVE?        -> MANDATE_SUSPENDED
        |                  MANDATE_EXPIRED
        v
CREDENTIALS VALID?     -> MISSING_CREDENTIAL
        |                  CREDENTIAL_REVOKED
        |                  CREDENTIAL_EXPIRED
        v
ACTION / ASSET / VENUE -> ACTION_NOT_ALLOWED
        |                  ASSET_NOT_ALLOWED
        |                  ADAPTER_NOT_ALLOWED
        v
VALUE LIMITS           -> TX_LIMIT_EXCEEDED
        |                  DAILY_LIMIT_EXCEEDED
        v
AUTHORIZED

Fundamental questions precede specific ones: whether this actor may use this mandate at all is settled before what the mandate allows. Valuation comes last, because it alone depends on an external price input, so a structurally invalid intent is refused without a price being consulted.

Order never changes the outcome — a conjunction returns the same result in any sequence — but it fixes which of several violated rules the operator hears about, and therefore what they do next.

Value denomination and the price input

A limit of $2,500 is not a statement about token quantity. Converting an intent's quantity into a denominated value requires a price for that asset at evaluation time, and that dependency belongs in the specification rather than in an implementation's assumptions.

Three consequences follow. The valuation currency and the price source belong in the mandate configuration rather than in implicit implementation behaviour, so that two evaluators reach the same answer for the same intent. A staleness bound must be stated: a quote older than the declared tolerance is not a usable price, and preflight refuses with INVALID_EXECUTION_CONTEXT. And influence over the price source is influence over limit enforcement in both directions, since a distorted price can make a large intent look small or a permitted one look oversized. Where the asset is itself the natural unit of risk, a limit denominated in units of that asset avoids the dependency, trading comparability across assets for independence from an external quote.

PASS constrains authorization risk, not market, smart-contract, oracle or governance risk. A mandate that evaluates correctly against a manipulated price is still evaluating against a manipulated price, and the security model treats that dependency directly.

Optional extensions

Extensions are defined by the architecture but are not required for conformance, and what is available depends on what the execution environment and the relevant adapter can observe. The Reason Code set is closed, so an extension introduces no new code: it maps onto an existing one, and the mapping is declared in the mandate rather than chosen at runtime.

Leverage and other risk constraints cap borrowed exposure or set a minimum margin. They are meaningful only where the adapter can read position state from the venue, since the constraint describes a position rather than an instruction. The usual mapping is ACTION_NOT_ALLOWED when the position type is disallowed outright and TX_LIMIT_EXCEEDED when an instruction would breach the ceiling.

Counterparty constraints restrict who may sit on the other side of an execution or receive a transfer, typically as a destination allowlist. They close the path where an otherwise permitted transfer of a permitted asset moves value outside the mandate's perimeter, and commonly map to ACTION_NOT_ALLOWED.

Concentration constraints cap how much of a portfolio may sit in one asset or category. They are stateful and require valuation of holdings rather than of a single intent, which widens the oracle surface described above. They commonly map to TX_LIMIT_EXCEEDED.

Emergency suspension controls halt a mandate without revoking it. Preflight reads mandate status in the core tier regardless; the extension supplies the control that places an active mandate into the suspended state, reported as MANDATE_SUSPENDED. Suspension is distinct from expiry because it is reversible, and the separate code lets an operator tell a paused mandate from a lapsed one without inspecting state. Whoever may suspend must be named in the mandate, because a suspension control is itself an authority.

Category reference

CategoryTierConstrainsReason Code
Actor bindingCoreWhether this actor may use this mandateACTOR_NOT_AUTHORIZED
Intent derivabilityCoreWhether the call can be described at allINVALID_EXECUTION_CONTEXT
Asset permissionsCoreWhich instruments an intent may referenceASSET_NOT_ALLOWED
Action permissionsCoreWhich operation class is permittedACTION_NOT_ALLOWED
Venue and adapter permissionsCoreWhich adapters may carry executionADAPTER_NOT_ALLOWED
Transaction limitsCoreValue of a single intentTX_LIMIT_EXCEEDED
Periodic exposure limitsCoreAggregate value within a windowDAILY_LIMIT_EXCEEDED
Valuation inputsCoreCurrency, price source and staleness boundINVALID_EXECUTION_CONTEXT
Credential requirementsCoreAttestations required in the passportMISSING_CREDENTIAL, CREDENTIAL_EXPIRED, CREDENTIAL_REVOKED
Temporal validityCoreWhen the mandate may be usedMANDATE_EXPIRED
Leverage and riskExtensionBorrowed exposure and marginACTION_NOT_ALLOWED, TX_LIMIT_EXCEEDED
CounterpartyExtensionPermitted destinations and counterpartiesACTION_NOT_ALLOWED
ConcentrationExtensionShare of portfolio in one asset or categoryTX_LIMIT_EXCEEDED
Emergency suspensionExtensionReversible halt of an active mandateMANDATE_SUSPENDED

Shape of a policy set

The interface below sketches the core tier: the shape of the data preflight reads. The actor and subject bindings sit on the mandate that carries the set, not inside the set.

interface PolicySet {
  assets: AssetId[]; // allowlist
  actions: ActionType[]; // allowlist
  adapters: AdapterId[]; // allowlist
  maxTransactionValue: Value; // per intent
  periodicLimits: PeriodicLimit[]; // windowed aggregate
  requiredCredentials: CredentialType[];
  valuation: ValuationConfig; // denomination and price input
  validFrom: Timestamp;
  validUntil: Timestamp;
  extensions?: PolicyExtension[]; // optional tier
}
 
interface PeriodicLimit {
  window: 'DAY' | 'WEEK' | 'MONTH';
  boundary: 'ROLLING' | 'CALENDAR';
  limit: Value;
}
 
interface ValuationConfig {
  currency: CurrencyCode;
  priceSource: PriceSourceId;
  maxQuoteAgeSeconds: number;
}

Expressed against the running example, the same structure carries concrete parameters.

{
  "actor": "0x81...29F",
  "subject": "0x3A...F02",
  "passport": "0x7F...94A",
  "policies": {
    "assets": ["AAPL", "NVDA"],
    "actions": ["BUY", "SELL"],
    "adapters": ["APPROVED_ADAPTERS_ONLY"],
    "maxTransactionValue": "2500.00",
    "periodicLimits": [{ "window": "DAY", "boundary": "ROLLING", "limit": "10000.00" }],
    "requiredCredentials": ["STOCK_TOKEN_ELIGIBLE"],
    "valuation": {
      "currency": "USD",
      "priceSource": "REFERENCE_FEED",
      "maxQuoteAgeSeconds": 60
    },
    "validFrom": "2026-01-01T00:00:00Z",
    "validUntil": "2027-01-01T00:00:00Z"
  }
}

The policy set above names no prohibition, and bridging is still refused: the action allowlist does not contain it, so there is no path by which a newly introduced action becomes permitted through omission. A mandate may additionally record an explicit prohibition, as the running example does for BRIDGE. That clause changes nothing on the day it is written and exists to constrain what a later amendment can accidentally permit, which is the reasoning set out in mandates.

The same vocabulary describes very different mandates. A delegated retail mandate and a desk-level institutional one differ in the values of their parameters and in which extensions they carry, not in the kinds of rules available to them. The specification fixes the categories and the codes; whoever assembles the mandate fixes the numbers.