Human approval checkpoints

Change one field after the reviewer approves

A small payload mutation is enough to test whether approval is bound to the action. Use a material field and verify that execution cannot reuse the earlier decision.

In this article

Start with an approved fixture

Create a synthetic order and a proposal to change its delivery address. Have an authorised test reviewer approve the saved proposal. Record the proposal revision, target version and operation identifier.

Confirm the approval screen displayed the same values stored in the proposal. Otherwise a later rejection may conceal an earlier mismatch between the interface and the record. The baseline should establish a valid decision before introducing the fault.

Keep execution paused so the test can alter the relevant boundary deliberately. Avoid relying on timing luck between a real click and a background worker.

Mutate the execution request

Attempt to submit the approved proposal with a different postcode, target order or destination identifier. The executor should load trusted proposal data and reject conflicting client-supplied values, or ignore fields that are not part of its accepted execution contract.

Next attempt to edit the stored proposal through the normal application API after approval. The application should reject the edit or create a new revision requiring review. Direct database edits are useful for separate corruption tests, but they do not establish whether ordinary API paths preserve the rule.

Test a material field that is easy to overlook, such as an attachment list or notification recipient. Approval can be undermined without changing the main headline value.

Change the world instead of the payload

Leave the proposal unchanged and move the order into a state where address changes are no longer permitted. Execution should apply the documented eligibility rule. An unchanged payload is not automatically safe when the target's business state has changed.

Repeat after the approval expires or the reviewer loses the required role. The expected behaviour depends on the organisation's approval policy, so encode that policy explicitly in the fixture rather than assuming every historical decision remains valid indefinitely.

Use concurrent execution attempts to verify that a valid approval does not produce duplicate mutations. This is a separate test from payload binding and should have a separate assertion.

Inspect the final record

Confirm that no unapproved value reached the target. Inspect proposal state, decision history and operation result, not just the error shown in the browser. A rejected response can arrive after an unintended write if validation occurred too late.

Keep the failure cases small and named by the property they test: changed payload denied, stale target blocked and repeated execution deduplicated. These assertions give future maintainers a clear signal when a new field or workflow path weakens the approval contract.

Primary sources

OWASP: transaction authorisationAWS Builders' Library: idempotent APIs

References checked 11 September 2026.