Skip to main content

Multi-Party Approval (MPA)

Multi-Party Approval (MPA) adds an additional layer of security by requiring multiple administrators to approve sensitive actions before they are executed.

Overview

When MPA is enabled, calls to protected API methods are not executed immediately. Instead, the request is queued and must be approved by the required number of workshop-admin users before it runs.

MPA protection is applied per RPC method. There is no longer a fixed set of "MPA commands" — protection can be attached to almost any mutating method, and some methods are protected automatically. Each method falls into one of the following categories:

  • Always protected — protection is enforced in code and cannot be removed.
  • Default protected — protection is seeded as a recommended default but can be modified or removed by an administrator.
  • Eligible — any other mutating method can be opted into protection.
  • Ineligible — a small set of methods that cannot be protected.

Protection can also be made conditional by attaching a CEL expression to a method, so that MPA is only required when the expression matches the request.

Protection Categories

Always-protected methods

These methods always require MPA when MPA is enabled. They cannot be removed or reconfigured through the API, which prevents an administrator from quietly stripping MPA protection off the controls that govern MPA itself (or off API key creation, which could otherwise be used to mint a privileged key and bypass approval).

  • SetMultipartyApprovalSettings
  • DisableMultipartyApproval
  • AddMPAProtectedMethod
  • RemoveMPAProtectedMethod
  • ResetMPAProtectedMethods
  • CreateAPIKey
  • UpdateAPIKey

Default-protected methods

When Workshop seeds the protected-methods list (on initial setup, or when the list is reset via ResetMPAProtectedMethods), it installs a recommended set of protections. Unlike always-protected methods, these can be modified or removed by an administrator after setup.

MethodCondition
KillProcessOnHostsWithTagAlways (no condition)
CreateRulerequest.rule.tag == "global"
CreatePackageRulerequest.rule.tag == "global"
CreateFileAccessRulerequest.rule.tag == "global"
CreateRulesFromBundleHashrequest.tag == "global"
DeleteRuleresource.tag == "global"
DeletePackageRuleresource.tag == "global"
DeleteFileAccessRuleresource.tag == "global"
BeginPasskeyRegistrationAlways (no condition)
DeletePasskeyAlways (no condition)
SetPasskeySettingsAlways (no condition)

The rule-related defaults are conditional: by default they only require approval when the action affects the global tag. The list view marks a default method as "drifted" when its condition has been changed from the seeded default.

Eligible methods

Any method with a write: permission can be added to the protected list (with an optional condition), except for the ineligible methods below. Use ListMPAProtectedMethods to enumerate everything that is currently protected along with everything that is still eligible to be added.

Ineligible methods

A small number of methods cannot be protected, because doing so would deadlock the approval system or serve no purpose:

  • ResolveMultipartyApprovalRequest — approving a request cannot itself require approval, or no request could ever be resolved.
  • ChatWithAI — a conversational action, not an administrative mutation.
  • PingAgent, CastVote, TestChatBot, TestBucket, ValidateCELRule — operational/diagnostic actions.
  • FinishPasskeyRegistration — the second half of the WebAuthn registration ceremony, kicked off by the (protected) BeginPasskeyRegistration call. The browser's WebAuthn flow cannot tolerate the finish step failing with an MPA challenge, so protection is enforced on BeginPasskeyRegistration instead.

Configuration

MPA can be configured in the Workshop Settings page under the "Multi-Party Approval" section, or through the API.

Required Approvers

Specify how many approvers a request needs before it executes. This value must be at least 2.

The requestor is counted automatically as the first approver but cannot cast an approval on their own request. So a value of 2 means the requestor plus one other workshop-admin; a value of 3 means the requestor plus two others, and so on. MPA cannot be enabled unless the organization has at least this many workshop-admin users.

Maximum Duration

Set the maximum time an approval request can remain pending before it automatically expires. Expired requests are rejected automatically. The default is 24 hours.

Exclude API Keys

When enabled, requests made with an API key bypass MPA and execute immediately. This is useful for automation that should not block on human approval. Note that this only exempts callers authenticating with an API key — human-initiated calls to protected methods (including CreateAPIKey and UpdateAPIKey) are still gated. API keys can never approve or reject MPA requests.

Conditional Protection with CEL

A protected method can have an optional CEL expression attached. When an expression is present, MPA is only required if the expression evaluates to true for that particular request; otherwise the call proceeds without approval. An empty expression means the method is unconditionally protected.

Two variables are available to expressions:

  • request — the incoming RPC request message. For example, request.rule.tag == "global" matches a CreateRule call whose rule targets the global tag.
  • resource — the resolved target of the request, for methods whose request only carries an identifier. For example, resource.tag == "global" on DeleteRule loads the rule being deleted and inspects its tag. The resource variable is only populated for methods that have a resolver registered (currently DeleteRule, DeletePackageRule, and DeleteFileAccessRule); for other methods it is an empty value.

Expressions must evaluate to a boolean and are validated when added — an invalid expression is rejected by AddMPAProtectedMethod.

Evaluation fails closed: if the resource cannot be resolved or the expression errors at runtime, the request is treated as requiring MPA rather than allowed through.

How It Works

  1. An administrator calls a protected method.
  2. If MPA is disabled, or the caller is an API key user and "Exclude API Keys" is enabled, the call proceeds normally.
  3. If the method has a CEL condition that evaluates to false for this request, the call proceeds normally.
  4. Otherwise, instead of executing, an approval request is created and the call returns a FailedPrecondition error carrying the transaction ID (x-mpa-txid).
  5. Other workshop-admin users view pending requests and approve or reject them.
  6. Once the required number of approvers is reached, the original caller re-issues the identical request. The interceptor finds the approved, unconsumed approval, atomically claims it, and executes the method exactly once. The result is recorded against the approval.
  7. If the request expires before reaching enough approvals, it is automatically rejected.

Because an approval is matched against the exact serialized request, the approved call must be re-issued with the same arguments to execute.

Security Considerations

  • Administrators cannot approve their own requests.
  • Each administrator can only approve a request once.
  • The requestor is counted as the first approver but does not cast an approval, so a genuine second admin is always required.
  • API keys can neither approve nor reject requests, so MPA cannot be bypassed by provisioning additional keys.
  • Approvals are consumed atomically before the handler runs, so a single approval cannot be replayed to execute the action more than once.
  • The requestor may cancel (reject) their own request even after it has reached the approval threshold, as long as it has not yet executed.
  • Protection for the methods that govern MPA itself — and for API key creation — is always enforced and cannot be removed.
  • All MPA activity (requested, approved, rejected, expired) is written to the audit log, linked by the request's transaction ID.

API Methods

Settings and requests

  • GetMultipartyApprovalSettings — Retrieve current MPA configuration (and the current workshop-admin count).
  • SetMultipartyApprovalSettings — Update MPA configuration.
  • DisableMultipartyApproval — Disable MPA (preserving other settings).
  • ListMultipartyApprovalRequestsForSession — List approval requests, including which ones the calling user can act on.
  • GetMultipartyApprovalRequest — Get details of a specific request by txid.
  • ResolveMultipartyApprovalRequest — Approve or reject a request.

Managing protected methods

  • ListMPAProtectedMethods — List currently protected methods (with their conditions, and whether they are always- or default-protected) along with all eligible methods that could be added.
  • AddMPAProtectedMethod — Protect an eligible method, optionally with a CEL expression.
  • RemoveMPAProtectedMethod — Stop protecting a method. Always-protected methods cannot be removed.
  • ResetMPAProtectedMethods — Remove all user-configured protections and restore the default set. Always-protected methods are unaffected.