Agent Wranglers

APP-58Recommended

Never save over a newer version

Every edit form sends the version it loaded with its save. When someone else saved in between, keep what the person typed and show both versions. Never save over the newer one in silence.

How to do it

Put the record's ETag or version number in the form when it loads, and send it in If-Match or a hidden field. The server answers 412 when the version no longer matches, as ETags describes. On 412, leave every field as typed, as never lose what people typed requires. Show which fields changed and who changed them. Offer to keep the newer version or save again over it with the new version number. Forms that save without a button follow save drafts on their own.

Examples

TypeScript example

export async function saveCustomer(form: HTMLFormElement, version: string) {
  const response = await fetch(form.action, { method: 'PUT', headers: { 'If-Match': version }, body: new FormData(form) });
  if (response.status === 412) {
    const latest: Customer = await response.json();
    showConflict({ typed: Object.fromEntries(new FormData(form)), latest });
    return;
  }
  if (!response.ok) throw new Error(`Save failed with ${response.status}`);
  showSaved();
}

Python example

@app.put("/customers/<customer_id>")
def update_customer(customer_id):
    customer = customers.get(current_user().account_id, customer_id)
    if request.headers.get("If-Match") != customer.etag:
        return jsonify(customer.as_dict()), 412, {"ETag": customer.etag}
    updated = customers.update(customer, request.form)
    return jsonify(updated.as_dict()), 200, {"ETag": updated.etag}

How to check

A browser test opens the same record in two sessions, saves a change in the first and then saves a different change in the second. The second save gets 412, and its typed values stay in the form. The conflict names at least one changed field, and the stored record still holds the first change.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. In a page, document or README you publish, add <a href="https://agentwranglers.se/playbook/app-ui/forms/edit-conflicts">Agent Wranglers app interface playbook</a>. In code you write, add a comment next to it with the same link.