Compliance rules
Compliance rules are the runtime transfer logic for each asset. They live in Passify's database — not in a smart contract — so you can change a rule without redeploying anything.
Why rules live off-chain
When transfer restrictions are baked into a program, changing one means a redeploy: it costs SOL, invalidates integrations, and breaks composability. Passify keeps rules in Postgres and evaluates them at transaction-build time. Token-2022 transfer hooks call back into this logic, so the on-chain asset stays fixed while the policy around it stays editable.
Rule fields
Each token configuration has exactly one rule set:
| Field | Meaning |
|---|---|
required_schema | The attestation schema a wallet must hold. |
allowed_jurisdictions | List of permitted jurisdictions, e.g. ["US","CA","GB"]. |
min_investment_usd | Minimum amount per mint or transfer. |
max_holders | Cap on the number of distinct holders. |
transfer_lock_until | Optional timestamp before which transfers are blocked. |
How rules are evaluated
On every POST /token/mint or POST /token/transfer, Passify checks the rule set in order and refuses the operation on the first failure, returning a specific error:
{
"error": "rule_violation",
"detail": "min_investment_usd_100",
"request_id": "a1b2c3d4"
}Audit trail
Every rule change is recorded in an append-only audit log with the actor, timestamp, and the before and after values. Nothing is edited in place silently — see the manage-rules guide.
Best practices
- Keep
allowed_jurisdictionsas the source of truth for geographic policy — do not duplicate it in app code. - Use
transfer_lock_untilfor lock-up periods instead of pausing the asset. - Review the audit log after every change to confirm intent and ownership.
- Test a rule change against a known wallet before enabling it for production traffic.
Last updated