DOCS / POLICY & RULES

Make permission programmable.

Define who may sign and what they may sign. Both signers enforce current rules independently.

Authentication, policy and application logic

LayerPurposeWhere it lives
Exact-request authenticationProve the authority authorized these bytes, key and expiry.Wallet signature or bound passkey/OIDC proof, verified privately by each signer.
Standard rulesRestrict destination, path, payload or signing availability.Optional compact Solana account, independently read by each signer.
Program rulesApply business logic and, when needed, consume persistent state.Your deployed program and authenticated application accounts.

Browser restrictions are convenience checks. They are not a replacement for signer or program enforcement.

No registration or policy setup required to start

V2 establishes public namespace metadata without registering an account on-chain. With no saved rules, every message still requires exact-request authentication. A read error is never treated as “no policy.” Once you create rules, their current revision remains authoritative.

Save policy on Solana and approve ordinary messages off-chain. This avoids per-message authorization transaction fees and approval-account rent. There is still RPC, service and signing work. Fully off-chain policy storage is deferred: an owner signature alone cannot prove that a policy is the latest revision.

Who authorizes a policy edit?

SourceRule-edit authorityPer-message Solana approval transaction
Solana accountAccount wallet signs the policy transactionNone for off-chain requests
Solana programProgram PDA authorizes a gateway CPI after application checksOnly for pairkey_approve_commit
PasskeyFresh WebAuthn P-256 assertion; a separate wallet may pay feesNone for off-chain requests
OIDCFresh issuer token and bound key; both signers attest the update, with a separate fee payerNone for off-chain requests

Creating or editing rules is a separate Solana transaction for every source. A new or enlarged rules account may require rent; same-size edits reuse it. Service, RPC and destination costs are separate from Solana authorization fees.

Account policy: create and edit

Your wallet authorizes edits with a Solana transaction signature. The policy address is derived from ["rules", namespace_digest] under the gateway. No prior namespace registration is required. Use the browser SDK from Quickstart: Account:

const current = await pairkey.rules(namespace);
const prepared = await pairkey.preparePolicy(namespace, {
  revision: current.rules.revision + 1,
  destinations: [key.account.destination],
  path_prefixes: [[0]],
  max_payload_bytes: 256,
  payload_prefix: [],
  disabled: false
});
await pairkey.setPolicy(namespace, wallet, prepared);

Creating or enlarging rules can require rent funding. Same-size edits reuse the account’s deposit and pay only transaction fees. A policy update does not require threshold signing. The controller can change its own policy; use a program with stricter governance if the controller itself must be constrained.

Passkey and OIDC policy

Passkey: identify the namespace by the credential’s compressed P-256 public key, RP ID and origin. For ordinary signing, authenticate a bound ephemeral Ed25519 key. For a policy edit, request a fresh WebAuthn assertion directly over the policy update challenge. Solana’s native P-256 verification checks that owner authorization; no MPC signature or per-edit ephemeral-key registration is needed.

import { passkeyAssertion } from './hosted-v2.mjs';
const update = await pairkey.preparePolicy(namespace, nextRules);
const assertion = await passkeyAssertion(namespace.identity, update.challenge, credentialId);
await pairkey.setPolicy(namespace, feePayerWallet, update, { Passkey: assertion });

A fee payer funds the transaction but gains no policy authority. This keeps passkey policy updates to one ordinary transaction and reuses the policy account. Setting rules is optional; it is not required before the first passkey-approved message.

OIDC: the issuer, audience and subject define the identity. Create the bound ephemeral key before preparing the update, and authenticate with its binding challenge as the OIDC nonce. The ephemeral key signs the exact update. Both signers independently verify the configured issuer’s ID token and attest the update; only those public attestations go on-chain.

import { ephemeralIdentity } from './hosted-v2.mjs';
const ephemeral = await ephemeralIdentity(namespace);
// Complete your configured OIDC provider's login using ephemeral.oidcNonce.
const update = await pairkey.preparePolicy(namespace, nextRules);
const authentication = await ephemeral.approvePolicy(update, idToken);
await pairkey.setPolicy(namespace, feePayerWallet, update, authentication);

No provider is enabled implicitly. JWTs and passkey assertions go only to private authentication endpoints; they are not included in public receipts or persisted job records. See the identity flow.

Program policy: evaluate or consume

Your program owns its application rules. Its management instruction authenticates the owner or governance process, verifies state account ownership and PDAs, and updates a monotonic revision. The example stores one policy per owner under ["pairkey-policy", owner], shared by that owner’s namespaces under the program.

RuleApproval path
Allowed destination/path, membership, enabled flag, current application statepairkey_approve: read-only RPC evaluation by each signer.
Consume one allowance, reserve cumulative budget, mark a proposal usedpairkey_approve_commit: change state and record exact approval atomically on Solana.

Simulation does not persist writes or reserve state. The supplied example implements an approval-count budget, not transaction parsing or cumulative financial spending. If signing fails after a commit, an allowance is not automatically refunded.

Optional standard PairKey rules can apply in addition to application rules. The example’s owner-authorized SetRules CPI manages those namespace-specific restrictions. Custom programs must authenticate all management calls and validate the exact operation before gateway CPI. See program integration.

Standard rule fields

FieldMeaning
revisionImplicit default 0; first saved revision 1; every edit increments exactly once.
destinationsOptional allowlist of destination digests. Null means unrestricted; an empty list allows none.
path_prefixesOptional allowed numeric prefixes. Null means unrestricted; an empty list allows none.
max_payload_bytesMaximum canonical committed payload size, at most 1,232 bytes.
payload_prefixRequired byte prefix of that payload, at most 128 bytes. Empty imposes no prefix.
disabledRefuse signing while true.

Solana and NEAR commit raw message bytes. EVM, Zcash and Bitcoin commit a serialized signing intent containing the key and typed message. A text prefix is therefore not a universal message filter across suites. Hosted raw messages are limited to 256 UTF-8 bytes independently of these policy bounds.

Update or stop permission

Read the current rules, choose the next revision and authorize the exact update. A stale edit is refused rather than silently rebased. Set disabled: true to stop new authorization; later re-enable through another authorized revision. There is no delete-to-default policy fallback.

Each signer checks fresh policy before signing and before releasing output. An observed newer policy fences stale prepared requests. These checks do not retract an issued signature or make destination execution atomic with a policy change. Keep destination nonces and replay rules in your application.

Sessions are deferred for v2

Bound ephemeral keys authenticate requests; they do not bypass policy or create a scoped session. The older native-transfer API retains its registered Policy, COMMIT, grant and revoke formats. It has different fields and supported payloads. New standard rules also constrain that legacy authorization path; switching endpoints does not remove them. An existing customized legacy policy needs explicit migration to v2 rules. See legacy sessions.

Put rules into your flow

See the Policy demo for sample pairkey_approve and pairkey_approve_commit instructions and how to create their program-owned rules. Continue with account rules, program rules or the hosted API.