A request shows “approved” in the interface. A notification was sent. Yet the operator cannot prove which amount the reviewer saw, whether the reviewer still had authority or whether a second submission created another request. A status column can describe an outcome without establishing that the decision was valid. Architecture work begins by identifying the invariant: the operation executed must correspond to the version and authority actually approved.

Write the invariant before the endpoint

Consider a fictional operational request with an amount, department, purpose and supporting documents. The approval applies to a specific version of that request. If the amount changes, the previous approval must not silently authorize the new value. A permission check must include organizational scope as well as role: an approver for one department must not approve another department’s request simply because both accounts have an “approver” label.

Document the allowed transitions and the person authorized for each one. A correction after approval may create an amendment, require another approval or cancel the request. The institution must choose that policy. An engineer should not infer it from whichever update endpoint is easiest to implement.

InvariantWhere it is enforcedEvidence
Only an authorized actor changes the stateServer-side policy using actor, organization and transitionNegative tests for other departments and revoked access
Approval refers to the reviewed versionExpected-version condition in the transactionConcurrent edit causes rejection
A repeated command has one business resultScoped command key and stored resultRetry after a lost response returns the recorded result

Treat version and authority as transaction inputs

The client supplies the expected version and an idempotency key, while the server derives the actor from authenticated context. Within one transaction, recheck the authoritative state and any authorization data that must remain consistent with it. Apply the transition conditionally, record the audit event and save the command outcome. A unique constraint or suitable locking strategy must protect competing attempts; a preliminary “does this key exist?” query alone is vulnerable to a race.

Command: approve(request_id, expected_version, command_key)
Transaction:
  authorize actor for this request and transition
  claim command_key within actor/organization scope
  require state = awaiting_approval and version = expected_version
  record approved version, decision and audit entry
  store command result; commit
Retry: return stored result for the same payload
Conflict: reject changed payload or stale version

This is design pseudocode, not a complete implementation. Key scope, payload comparison, expiry, revocation and lock ordering require explicit decisions. PostgreSQL documents different isolation guarantees; using a transaction does not make every read–check–write sequence safe. Test the selected concurrency strategy with two competing sessions and retry the whole transaction when the chosen isolation level requires it.

Keep notification delivery outside the authority boundary

If approval is committed but email delivery fails, a request should not revert to an unapproved state simply to match the inbox. Record a notification intention in the same transaction as the decision, then let a worker deliver it. The transactional outbox pattern addresses this dual-write boundary. Delivery may repeat, so downstream handling must be idempotent. A successful send and a valid approval are different facts.

Plan the ambiguous timeout

An interrupted connection leaves the client uncertain, not necessarily the server. The command may have committed before the response disappeared. Repeating it with a new identifier discards the mechanism that could recognize the first attempt. Keep the original key, query its result and distinguish “not accepted,” “accepted,” and “outcome still unknown.” An offline draft is not an accepted request and should be labelled accordingly.

What to verify before calling it reliable

  • Submit two approvals against the same expected version; verify only the permitted transition wins.
  • Lose the first response, repeat the same key and verify the original business result is returned.
  • Reuse a key with a different payload and verify rejection rather than accidental replay.
  • Change the record before approval and verify that the reviewer must inspect the new version.
  • Stop the notification worker, commit a decision and verify recoverable delivery after restart.

These tests expose a useful consulting boundary. The business owns the authority policy; the architecture translates it into state, concurrency and recovery rules; implementation must demonstrate those rules. If a system cannot explain that chain, adding another approval screen will not establish integrity.

Technical references