Stop Stale Shipping Instructions with ETags and Revision-Bound Approval
A document coordinator opens shipping instructions. Another colleague corrects a package count. The first coordinator saves an older screen and accidentally restores the previous count. A PDF generated a minute later looks polished, but contains the overwritten value.
The useful API contract is not “save the latest form.” It is “save this change only if the document is still the version that was reviewed.”
The endpoints, identifiers and document workflow below are hypothetical. They are synthetic software examples, not Zenith Eclipse integrations or carrier instructions.
Return a validator with the editable representation
An authenticated read can return:
HTTP/1.1 200 OK
Content-Type: application/json
ETag: "si-demo-r12"
{"id":"si-demo","revision":12,"packageCount":80,"state":"draft"}
The client preserves that ETag and submits it on the next write:
PUT /shipping-instructions/si-demo
If-Match: "si-demo-r12"
Content-Type: application/json
{"packageCount":82}
Here the illustrative PUT endpoint replaces the complete editable field set, which contains only packageCount. A real endpoint must document its complete replacement schema or use an explicitly defined partial-update contract.
RFC 9110, section 13.1.1 defines If-Match and requires strong comparison. A weak validator prefixed with W/ is unsuitable for this check. If-Match with an asterisk checks existence; it does not protect the specific revision the editor saw.
Generate validators so that every relevant representation change produces a new value. A revision number is adequate only if all writers advance it and representation variants cannot reuse the same strong validator for different bytes.
Enforce the check at the write boundary
Do not compare a revision in application memory and then perform an unconditional update. Make comparison and mutation indivisible.
One implementation uses a database update conditioned on tenant, document identity and expected revision. It increments the revision in the same statement. Alternatively, lock the document row, check the validator and perform the change within the transaction. PostgreSQL documents the blocking behavior of row locks.
On an ordinary stale write, return 412 Precondition Failed and leave the document untouched. Require the application's chosen precondition on edit endpoints; do not silently accept clients that omit it. Authentication and authorization remain separate from concurrency checks.
The client should retain unsaved edits, fetch the current document and show the difference. Automatically retrying with the new ETag would defeat the protection by overwriting work the user never reviewed.
Approve an immutable snapshot
An approval should name a document revision, reviewer role and decision time. “Approved=true” on a mutable document does not establish which package count was accepted.
Use a separate approval action with the expected revision. Its transaction verifies that the document remains at that revision and that the caller may approve it. An edit after approval creates a new unapproved revision under this proposed workflow.
Generate the PDF from the approved snapshot, including party addresses and line items captured in that snapshot. Do not mix an old document revision with live customer-master data.
The snapshot's fields depend on the shipment. Zenith Eclipse's full-container-load shipping scope identifies container, seal, weight and shipping-instruction responsibilities; its less-than-container-load shipping scope emphasizes package measurements and consolidation handling. Use that distinction when defining a document schema, while retaining the actual carrier's requirements and the exact values approved for the specific shipment. Store the rendered artifact's identifier, source revision and rendering-template version.
A corrected customer address should create a deliberate document revision where required. Updating the address book must not silently change a previously issued artifact.
Keep internal approval separate from external acceptance
A successful API save means the internal record changed. It does not mean a carrier accepted revised shipping instructions or that an issued transport document can be amended.
Track external submission and acceptance against the exact revision sent. A later internal edit must not inherit the earlier external acceptance. The actual provider contract determines permissible amendments and response handling.
Test two simultaneous edits, approval racing with an edit, stale approval, and PDF generation after master-data changes. An ambiguous network response requires reconciliation with the current revision before another mutation.
ETags solve stale-write detection. Revision-bound approvals and snapshots solve a different question: which exact information was reviewed, rendered and submitted? A dependable document workflow needs both.
About the publisher: Zenith Eclipse Co works across agricultural commodities, international logistics and machinery sourcing.
Comments
Join the discussionNo comments yet. Be the first to comment.