Skip to main content

Core Concepts

Quorum authorization connects product users to network-verifiable credentials. The Wallet backend decides which application users can begin a flow; MPC Nodes decide whether the submitted credentials authorize the key action.

Components and responsibilities

ComponentResponsibility
Client or ApproverUses an EOA, passkey, or JWT credential to authenticate one exact request without revealing the client's secret
Wallet backendFreezes the request, collects signatures, and groups them as default, approvals, and grantees
MPC NodesThe initiator node receives and broadcasts the request; every participating node verifies the signatures against its keyshare, grants, and policy before independently authorizing the action
Policy engineUses the authenticated initiator, exact approvers, transaction, and policy to select matching rules, evaluate conditions, and count approvals

The Wallet backend owns application-specific user and role management. MPC Nodes do not receive or interpret those roles. They authorize requests using verified credential identities, key-bound grants, and policy rules.

Approval groups and member identities

An approval quorum defines which credentials approve an action and how many approvals are required.

Member identity

An approval member is an exact pair:

(authentication method, credential ID)
MethodCredential ID
EOARecovered 20-byte account address
PasskeyVerified WebAuthn credential ID
JWTDerived string ID for the verified issuer and subject

EOA, passkey, and JWT credentials can be approval members. Ephemeral session keys may initiate an allowed signing request, but they cannot be approval members and never contribute a quorum vote.

The configured voting unit is one credential, not one person. A Wallet backend that requires distinct members must ensure that configured credentials belong to distinct administrators.

Quorum Approval

The Policy structure defines separate approval quorums for signing and policy management:

{
"version": "1.0",
"epoch": 4,
"management_approval": {
"members": [
{ "method": "eoa", "id": "0x111..." },
{ "method": "passkey", "id": "passkey-a" },
{ "method": "jwt", "id": "derived-jwt-id" }
],
"threshold": 2
},
"rules": [
{
"issuer": [{ "type": "UserId", "id": "key-user" }],
"approval": {
"members": [
{ "method": "eoa", "id": "0x222..." },
{ "method": "passkey", "id": "signer-a" }
],
"threshold": 2
},
"action": "allow",
"chain_type": "ethereum",
"conditions": [
{
"transaction_type": "eip191",
"transaction_attr": "message",
"operator": "eq",
"value": "Approve payroll"
}
]
}
]
}
  • issuer defines the initiator of the signing request, which required to be matched for the rule evaluation.
  • Rule.approval names the quorum of the Transaction Approvers, and the threshold. For example, the quorum is [Alice, Bob, Charlie] with threshold 2, meaning only 2 signatures from any of the quorum members is required.
  • management_approval names the Quorum of Policy Admins, allowed to do policy update and deletion.
  • threshold is the number of distinct quorum members whose valid signatures must accompany the request. It must be at least 2 and cannot exceed the number of members.

Key-bound approval capabilities

MPC Nodes bind policy members to the key through credential grants. They maintain one grant per credential and key:

CredentialGrant
|- key_id
|- identity: method + credential_id
|- capabilities
CapabilityMeaning
approve_signingThe credential is eligible to approve signing requests governed by a matching Rule.approval
approve_policy_managementThe credential is eligible to approve policy updates and deletions governed by management_approval
authorization_rootThe credential authenticated DKG and remains the policy-management initiator

Approval capabilities are eligibility to vote. They do not independently allow a credential to initiate signing or modify policy.

MPC Nodes derive approval capabilities from Policy membership:

Policy locationDerived capability
management_approval.membersapprove_policy_management
Any rules[].approval.membersapprove_signing

A credential appearing in both locations receives both capabilities. The authorization root is created once during DKG and is not derived from policy.

Authentication roles

Every request carries the signatures of the members taking part, each one in a named field. The field name is what tells MPC Nodes what that signer is doing.

Which fields a request may carry depends on where it sits in the life of a quorum:

StageRequestWhat its signatures do
Set it upDKGFix who the first members are, using the policy carried in the same request
Change itupdatePolicy, deletePolicyLet the current members approve a new policy, and let anyone gaining capability accept it
Use itSigningLet the members named by a matching rule approve one transaction

A quorum can only approve once it exists, so the three shapes below are not interchangeable. MPC Nodes reject a field that does not belong to the request being made.

In a keygen request

DKG is where a quorum begins. The policy travels inside the DKG request itself, so there is nothing stored on the key yet and no one to approve against. The signatures establish who the members are.

One DKG request can create a key for several signing algorithms at once, and each key is authenticated on its own, so every field is labelled with the algorithm it belongs to:

FieldWho signsCounts as an approval?
<sign-alg>The initiator who creates this keyNo. There is no quorum yet. This credential becomes the key's authorization root
<sign-alg>/grantees[]Every credential the key's initial policy names, except the rootNo. It only proves that the credential's holder agrees to the grant
const userSignatures = {
secp256k1: secpRootSignature,
'secp256k1/grantees': [adminASignature, adminBSignature],
ed25519: edRootSignature,
};

There is no approvals field here. A new key has no approvers yet.

In a Policy administrative request

Administrative requests can change the quorums that already exists. The policy stored on the key authorizes its own replacement: the current members approve the change, and who the change gives new capability.

FieldWho signsCounts as an approval?
defaultThe initiator who starts the requestYes, only if their credential is also a member of the quorum for this action
approvals[]Everyone approving the requestYes, once for each signer who is a member of the quorum for this action
grantees[]A credential that this request is adding to the policy, or giving more permission toNo. It only proves that the credential's holder agrees to the change
const userSignatures = {
default: initiatorSignature,
approvals: [adminASignature, adminBSignature],
grantees: [newMemberSignature],
};

The default signature is always required to authenticate the request. It can be counted as an approval if the signer is also a member of the quorum for this action.

An admin's signature can appear in both approvals and grantees in the same update. For example, an admin who approves an update that also adds him to a rule's signing quorum. Then, his signature proves the approval of the update with the authority he already holds, and separately proves his consent to the new signing capability.

In sign request

The quorum defined in Policy's rules authorizes the right members to approve the transaction to be signed.

FieldWho signsCounts as an approval?
defaultThe initiator who starts the request. Their credential must match a rule's issuer for that rule to applyYes, only if their credential is also a member of that rule's approval
approvals[]Everyone approving this transactionYes, once for each signer who is a member of the matching rule's approval
grantees[]Nobody. Signing hands out no new capability, so MPC Nodes reject any entry hereNot applicable
const userSignatures = {
default: initiatorSignature,
approvals: [signerASignature, signerBSignature],
grantees: [],
};

An ephemeral session key can start a signing request, but it cannot be an approval member.

Authorization lifecycle per key

Policy changes update the approval groups and their key-bound grants together. This produces two authorization states for a key:

Loading Diagram...
EventGrant and policy result
DKG without policyRoot grant only; authorization epoch 0
DKG with policyRoot plus policy-derived grants; epoch 1
Policy updateAdd, change, or remove policy-derived grants atomically; advance epoch once
Policy deleteRemove the policy and every policy-derived grant; retain root; advance epoch once
Recreate policy without approval groupsRoot authenticates alone; no approval grants are created

The epoch belongs to the key: each Policy update must commit the next epoch and Policy deletion carries the current epoch as the expectedAuthorizationEpoch field of DeletePolicyRequest, preventing a stale mutation from applying to newer authorization state.

Continue to Authorization Process for independent signature collection and MPC Node evaluation.