@pearldigital/p3-agentic-credential-schemas
v1.0.2
Published
Credential primitives for the P3 Agentic Registry — types, canonicalization, hashing, and validation
Readme
p3-agentic-credential-schemas
Credential primitives for the P3 Agentic Registry — types, JSON schemas, canonicalization, hashing, and validation for DelegationCredentials.
This package defines the off-chain data structures that anchor autonomous agent authority on-chain. A DelegationCredential is the core artifact: it encodes a principal's delegation of specific capabilities to an agent, subject to jurisdictional, temporal, and token constraints. The credential is canonicalized, hashed (keccak256), and the resulting poaHash is stored on-chain by P3AgenticRegistryManager.registerAgent().
Overview
DelegationCredential
├── version "1.0.0"
├── principal 0x… (OnChainID of delegating entity)
├── agent 0x… (wallet receiving authority)
├── capabilities[] what the agent can do
│ ├── action "transfer" | "mint" | "burn" | "receive"
│ ├── target contract address or "*" (wildcard)
│ ├── maxValue per-invocation limit (base units)
│ └── cumulativeLimit lifetime limit (base units)
├── policy where/when it's valid
│ ├── jurisdictions ISO 3166-1 numeric codes
│ ├── notBefore unix timestamp
│ ├── notAfter unix timestamp
│ └── allowedTokens optional token whitelist
└── label optional human-readable nameOn-Chain Hash Anchoring
delegation-credential ── canonicalize ── keccak256 ──▶ poaHash (bytes32)
├── capabilities[] ── canonicalize ── keccak256 ──▶ capsetHash (bytes32)
└── boundary-policy ── canonicalize ── keccak256 ──▶ policyHash (bytes32)These three hashes are stored in the on-chain AgentRecord by P3AgenticRegistryManager.registerAgent(), providing a tamper-proof link between the off-chain credential document and the on-chain agent registration.
Installation
pnpm add @pearldigital/p3-agentic-credential-schemasRequires Node.js >= 18. The single runtime dependency is viem (for keccak256 and toHex).
Quick Start
import {
type DelegationCredential,
hashAll,
validateCredential,
evaluatePolicy,
} from "@pearldigital/p3-agentic-credential-schemas";
// 1. Define a credential
const credential: DelegationCredential = {
version: "1.0.0",
principal: "0x1234567890abcdef1234567890abcdef12345678",
agent: "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd",
capabilities: [
{
action: "transfer",
target: "*",
maxValue: 10_000_000_000n, // $10,000.00
cumulativeLimit: 50_000_000_000n, // $50,000.00
},
{ action: "receive", target: "*" },
],
policy: {
jurisdictions: [48], // Bahrain
notBefore: 1700000000,
notAfter: 1731536000,
},
label: "Treasury rebalancing agent",
};
// 2. Validate
const { valid, errors } = validateCredential(credential);
// valid → true, errors → []
// 3. Hash for on-chain registration
const { poaHash, capsetHash, policyHash } = hashAll(credential);
// poaHash → 0x… (bytes32, stored as AgentRecord.poaHash)
// capsetHash → 0x… (bytes32, stored as AgentRecord.capsetHash)
// policyHash → 0x… (bytes32, stored as AgentRecord.policyHash)
// 4. Evaluate at runtime — is this operation allowed right now?
const evaluation = evaluatePolicy(credential, {
timestamp: Math.floor(Date.now() / 1000),
jurisdictionCode: 48,
action: "transfer",
value: 5_000_000n, // $5.00
});
// evaluation.valid → true/false
// evaluation.errors → ["credential expired", ...]API Reference
Types & Constants
| Export | Description |
|:-------|:------------|
| DelegationCredential | The core credential document type |
| Capability | A single granted capability (action, target, value limits) |
| BoundaryPolicy | Jurisdictional, temporal, and token constraints |
| AgentRegistrationParams | Full parameter set for registerAgent() on-chain |
| AgentLimits | Per-agent transaction limits (single send, rolling window) |
| RiskClass | Agent risk classification (1=LOW, 2=MEDIUM, 3=HIGH, 4=CRITICAL) |
| AgentLifecycleState | On-chain lifecycle states (DRAFT → PENDING_MLRO → APPROVED_ACTIVE → SUSPENDED → REVOKED) |
| AGENT_CAPABILITIES | Capability bitmap constants (TRANSFER=0x0001, BURN=0x0002, MINT=0x0004, RECEIVE=0x0008) |
| RISK_CLASS | Risk class enum constants |
| AGENT_LIFECYCLE_STATE | Lifecycle state enum constants |
Canonicalization
Deterministic serialization that ensures the same logical credential always produces the same hash, regardless of property ordering or serialization quirks.
| Function | Input | Output | Rules |
|:---------|:------|:-------|:------|
| canonicalize(credential) | DelegationCredential | string | Full credential → sorted-key JSON |
| canonicalizeCapabilities(capabilities) | Capability[] | string | Capabilities only |
| canonicalizePolicy(policy) | BoundaryPolicy | string | Policy only |
Canonicalization rules:
- Ethereum addresses are lowercased
bigintvalues are converted to decimal strings- Capabilities are sorted by
action(lexicographic) - Jurisdictions are sorted numerically
allowedTokensare lowercased and sorted lexicographically- Object keys are ordered alphabetically
- Output is
JSON.stringify()with no whitespace
The canonical serialization must produce identical output to the on-chain Solidity equivalent. Any change to canonicalization is a breaking change.
Hashing
Produces keccak256 hashes from canonicalized representations. These are the bytes32 values stored on-chain.
| Function | Returns | On-Chain Field |
|:---------|:--------|:---------------|
| hashCredential(credential) | 0x${string} | AgentRecord.poaHash |
| hashCapabilities(credential) | 0x${string} | AgentRecord.capsetHash |
| hashPolicy(credential) | 0x${string} | AgentRecord.policyHash |
| hashAll(credential) | { poaHash, capsetHash, policyHash } | All three |
Validation
Schema validation — checks structure, types, and constraints (no runtime context needed):
| Function | Validates |
|:---------|:---------|
| validateCredential(credential) | Full credential: addresses, version, capabilities, policy, duplicates |
| validateCapability(capability) | Single capability: action, target format, value consistency |
| validatePolicy(policy) | Policy: jurisdictions (1-999, unique), temporal bounds, token addresses |
All return { valid: boolean, errors: string[] }. Errors are collected (not fail-fast), so you get the complete picture in one call.
Runtime evaluation — checks a credential against a live context:
evaluatePolicy(credential, {
timestamp?: number, // is the credential active? (defaults to now)
jurisdictionCode?: number, // is this jurisdiction permitted?
tokenAddress?: string, // is this token in allowedTokens?
action?: string, // does any capability grant this action?
value?: bigint, // is this value within maxValue?
})All context fields are optional — omit any you don't need to check.
JSON Schemas
The schemas/ directory contains JSON Schema (draft 2020-12) definitions for all off-chain data structures. These can be used with any compliant validator (e.g., ajv, @cfworker/json-schema).
| Schema | File | Hashes To |
|:-------|:-----|:----------|
| DelegationCredential | schemas/delegation-credential.schema.json | poaHash |
| Capability | schemas/capability.schema.json | (part of capsetHash) |
| BoundaryPolicy | schemas/boundary-policy.schema.json | policyHash |
| AgentRegistration | schemas/agent-registration.schema.json | registerAgent() calldata |
Import schemas directly:
import schema from "@pearldigital/p3-agentic-credential-schemas/schemas/delegation-credential.schema.json";See schemas/SCHEMAS.md for full field-level documentation, examples, and the capability bitmap reference.
Token Precision
All value fields use 6-decimal microunits consistent with P3 token precision:
| Human Value | Base Units | String |
|:------------|:-----------|:-------|
| $1.00 | 1,000,000 | "1000000" |
| $1,000.00 | 1,000,000,000 | "1000000000" |
| $10,000.00 | 10,000,000,000 | "10000000000" |
Integer math only — no floating point. UI displays floor to 2 decimal places.
On-Chain Capability Bitmap
The action field in capabilities maps to the P3AgentCapabilities Solidity library:
| Action | Bitmap | Hex | Description |
|:-------|:-------|:----|:------------|
| transfer | 0000 0001 | 0x0001 | Agent sends tokens |
| burn | 0000 0010 | 0x0002 | Agent's tokens are burned/redeemed |
| mint | 0000 0100 | 0x0004 | Tokens minted to the agent |
| receive | 0000 1000 | 0x0008 | Agent receives incoming transfers |
On-chain, capabilities = 0 means unconfigured (unrestricted, backward-compatible). Any non-zero value means only the explicitly granted bits are permitted.
Agent Lifecycle
After registration via registerAgent(), agents follow this on-chain lifecycle:
registerAgent()
│
▼
PENDING_MLRO ──▶ approveAgent() ──▶ APPROVED_ACTIVE
│ ▲
▼ │
SUSPENDED ───┘
│ reactivateAgent()
▼
REVOKED (permanent)Approval sets validFrom. Revocation is irreversible. If a Principal is removed from the registry, all their agents are lazily invalidated (cascading kill switch).
Development
# Install dependencies
pnpm install
# Build
pnpm build
# Run tests
pnpm test
# Watch mode
pnpm test:watchStack: TypeScript (ES2022, ESM), Vitest, viem.
Project Structure
src/
types.ts TypeScript interfaces, constants, and enums
canonicalize.ts Deterministic serialization functions
hash.ts keccak256 hashing (via viem)
validate.ts Schema validation and runtime policy evaluation
index.ts Public API barrel export
schemas/
delegation-credential.schema.json Root credential schema
capability.schema.json Capability sub-schema
boundary-policy.schema.json Policy sub-schema
agent-registration.schema.json Registration parameter schema
SCHEMAS.md Full schema reference documentation
tests/
fixtures.ts Deterministic test credentials
credential/
canonicalize.test.ts Canonicalization snapshot tests
hash.test.ts Hash determinism tests
policy/
validate.test.ts Validation and evaluation testsChangelog
See CHANGELOG.md for the release history. Versions follow Semantic Versioning and are published automatically by CI.
License
Pearl Digital Source-Available License v1.0 — Copyright (c) 2026 Pearl Digital Issuance Company B.S.C.(c)
This software is source-available but not open source. You may use it free of charge solely in connection with the P3 Agentic Registry and its officially supported tooling. Modification and redistribution are not permitted. See LICENSE for full terms.
