Field notesInterface design

Make an approval mean one specific action

An approval button is ambiguous when it says only “Continue.” Continue with which operation, on which resource, using which version of the inputs? If the request can change after the operator approves it, the interface has asked a clear-looking question with a moving answer.

A useful approval authorizes one defined operation. AXON’s concept of scoped action can be made concrete by treating approval as a short-lived contract between a proposed change and the service that will execute it.

Define the operation before the button

Consider publishing article 42, revision B, to the public site. The confirmation should name that article, show the relevant changes, explain that publication is public, and state when the approval expires. “Approve publishing” is more informative than “Approve agent.”

{
  "action": "article.publish",
  "resourceId": "article-42",
  "revision": "example-revision-b",
  "visibility": "public",
  "approvalScope": "one-operation",
  "expiresAt": "2026-10-28T12:10:00Z"
}

This is a fictional contract, not a real pending request. A production version would also bind the authenticated approver, the policy version, and a canonical representation of the approved input. A hash is useful only if the server computes and verifies it over the same defined data.

Use three separate checks

  1. Can this actor request the action? Authentication and authorization establish the requester’s permission to act on this resource.
  2. Does this action require approval? A policy evaluates its scope and consequence, not just which screen initiated it.
  3. Is this approval still valid at execution? The service verifies the resource version, approved payload, expiry, and revocation state immediately before applying the operation.

The third check is easy to miss. The article may have changed, a user’s permission may have been revoked, or the approval may have expired while the job waited in a queue. Reusing the earlier UI state without reevaluation creates a time-of-check/time-of-use gap.

Make state transitions visible

A proposed state model for one publishing operation
StateWhat the operator should seePermitted next step
Awaiting approvalExact proposed revision and effectApprove or reject
ApprovedApprover, scope, and expiryExecute only while the contract still matches
Changed or expiredThe reason approval no longer appliesRequest approval for the new operation
Rejected or revokedA clear denial stateStop; do not silently retry with wider authority
Attempted; outcome unknownWhat was sent and what is unverifiedReconcile before repeating the side effect
Verified completeEvidence of the applied revisionOffer a supported follow-up, if one exists

Do not collapse “approved” into “completed.” Approval is permission; completion is an observation about an operation. A queue can fail after permission was granted. The action-record guide shows how to preserve that difference.

Expand scope deliberately

Repeated approvals can become noise. Reduce that noise by making the policy more specific, not by hiding every gate. For example, an operator might allow saving drafts in one workspace while retaining approval for public publication.

A progression could start with read-only observation, allow proposed changes, then permit a narrow set of reversible actions. Expanding authority requires an explicit resource boundary and revocation path. “Autonomous mode” is not a sufficiently precise permission description.

Explain why a gate appeared and how its scope differs from a previously allowed action. That lets an operator correct an overly broad request instead of repeatedly granting exceptions they do not understand.

A disabled control is only the visible layer

The repository’s supporter checkout contains disabled provider controls for sign-in options that are not enabled in its configuration. That can prevent a visitor from taking a broken path. It does not authorize other actions or secure a server endpoint.

Likewise, removing a pricing section or a checkout link does not disable the underlying checkout route. The earlier version of this note described the supporter pass as withdrawn in a way that implied the route was gone. The source still contains that route and payment integration. UI availability and service availability must be described separately.

For a real approval system, enforce the boundary server-side on every request. Client-side checks provide feedback; a caller can bypass the page. Treat duplicate submission and replay as part of the execution design rather than trusting that a disabled button prevents them.

Review the contract with adversarial timing

Change the resource between approval and execution. Revoke the approver’s access. Submit the same operation twice. Let the approval expire in a queue. Lose the network response after the side effect. A good design specifies the resulting state for each case before someone implements the happy-path animation.

The current AXON page does not implement these tests or this policy service. Its role is to make the proposal understandable. The reusable lesson is the contract: a specific actor approves a specific operation over specific inputs, and the execution service checks that contract when it matters.

Sources & revision

Read the dated source excerpt. It includes original file paths, line numbers, and SHA-256 hashes for the version used in this guide. The public repository may contain a different revision.

28 Oct 2026: Replaced broad guardrail claims with a concrete approval contract and state table. Corrected the claim that removing pricing had disabled the supporter checkout.

These notes use AI assistance. Read the editorial method and corrections policy. Found an error? Send a correction with this article’s title.