Problem/Motivation
The unreleased paragraph draft-translation endpoint accepts a revision ID as its update precondition but can save on that same revision. Two clients can therefore reuse one token and overwrite an intervening translation edit. The shared-status fallback also updates host references without host concurrency preconditions.
Steps to reproduce
- Create an unpublished paragraph translation on a translatable-status bundle.
- Read it from two clients.
- Update from client A, then update from client B using the original revision ID. Both writes are accepted.
Proposed resolution
Return an opaque draft state token and require it on paragraph PATCH, including preflight. Recheck authoritative revision state under the paragraph lock. Refuse shared-status translations before mutation, and roll back unexpected new paragraph revisions instead of repinning hosts. Node draft translations and image alt remain supported.
Remaining tasks
Verify stale read/write and preflight cases, English publication and text preservation, and host-pointer preservation. Update the connector to preserve and require the state token. Complete supported-version CI before release.
API changes
Paragraph responses return meta.draft_state. Paragraph PATCH requires X-MCP-Draft-State. Unsupported shared-status or new-revision saves return a conflict. No data model or configuration changes.
Comments
Comment #2
jmcerdaReleased in 2.17.0. Paragraph PATCH now requires and checks draft state under the row lock, including preflight. Shared-status translations and unexpected new revisions fail closed without repinning host references. Regression coverage verifies stale-write refusal, English preservation, and host-reference preservation. The Drupal 10.6/11.3, PHP 8.3/8.4, functional, and PostgreSQL draft suites passed. The companion connector 2.15.0 carries and requires the state token.