Shuttle Docs

updatePolicy

Change a policy through an explicit, ordered change set.

GroupOperation permissions
RuntimesTypeScript browser/server, React client adapter, Python/Go server; explicit owner/admin authority required
Updated2026-09-15

Status

Proposed target SDK behavior for implementation. It is not an available policy engine or released expression grammar.

Business action#

Replace a policy definition under its stable identity while preserving explicit wallet applicability.

Proposed call#

updatePolicy(
  input: UpdatePolicyInput,
  options?: CallOptions,
): Promise<Operation<UpdatePolicyResult>>

TypeScript uses requestId, policyId, expectedVersion, a complete definition, actor, and optional authorization. Replacement is explicit; omitted or null members do not silently clear prior meaning.

Go uses RequestID, PolicyID, ExpectedVersion and Definition; presence-aware fields and explicit definition variants prevent zero-value clearing. Cancellation after SDK dispatch requires GetOperation recovery, even when backend acceptance was not observed.

Required input: requestId, policyId, expected version, complete replacement definition, actor and authorization when required. The definition includes effect, condition, agreement requirement and notes.

Result and effects#

Success returns the next policy version and explicit applicability impact. A successful update changes the definition under the same stable policy ID; it does not create a second assignment step for wallets that already target that ID. All existing assignments observe one backend-defined atomic cutover from the expected prior version to the returned next version, or the operation fails and all remain on the prior version. A binding must not create a partial fleet of rule meanings. Assigning the policy to a new wallet or removing it from any wallet remains an explicit updateWallet action.

For example, changing a previously assigned bounded-transfer rule to require independent approval above a lower risk threshold creates one next revision after the version guard and authorization succeed. This is a semantic example, not runnable expression or quorum syntax. A concurrent stale update changes nothing; an in-flight action must be evaluated against the version boundary defined by the accepted backend contract, never whichever revision is convenient.

Four operations remain distinct: replace a definition with updatePolicy; remove one wallet assignment with updateWallet; retire/delete a definition through a separately accepted lifecycle; revoke an actor's wallet right with updateWallet. Removing a restrictive assignment is not actor revocation, and changing a definition cannot bypass immutable owner, minimum-agreement, recovery or last-authorized-actor guards.

Same-ID/same-material replay converges; changed material conflicts. Unknown outcomes use getOperation. Denial, stale version, expiry or insufficient agreement leaves the prior definition effective.

Agreement lifecycle#

Existing authority may complete the update. Otherwise the SDK either uses the application handler and submits its response once or returns requiresAction for explicit continuation; it cannot do both. Responses bind the exact policy version, replacement material, actor and request ID and are accumulated separately from immutable operation material. Incomplete agreement has an explicit non-success state rather than an unfinished promise.

A browser may initiate the change only for an explicitly authorized owner/admin actor. The backend rechecks that authority and the expected version; login, session refresh or frontend state never elevates policy rights.

Acceptance#

See Policies, Approvals, createPolicy, updateWallet, and getOperation.