Skip to content

feat(mls/database): add expected_field_value to UpdateMetadataData.V1 - #343

Merged
tylerhawkes merged 1 commit into
mainfrom
tyler/appdata-cas-expected-value
Aug 19, 2026
Merged

feat(mls/database): add expected_field_value to UpdateMetadataData.V1#343
tylerhawkes merged 1 commit into
mainfrom
tyler/appdata-cas-expected-value

Conversation

@tylerhawkes

@tylerhawkes tylerhawkes commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Adds a compare-and-swap guard to the local metadata-update intent payload.

Why

UpdateMetadataData.V1 is the payload libxmtp stores for a queued metadata-update intent. It carries an absolute field_value frozen at queue time. When a client's published intent loses an epoch race, libxmtp rebuilds the commit from that same frozen payload and republishes it on the new epoch — so a concurrent change from another member is applied, observed, and then silently overwritten by the stale local value.

That is fine for last-writer-wins fields. It is not fine for app_data, where clients hold structured state they reconcile themselves: the overwrite discards another member's write with no signal to either side.

expected_field_value lets the publisher express "set this field to X, but only if it is still Y". libxmtp abandons the intent instead of republishing when the guard does not match, and surfaces that to the caller so it can re-merge against the value that actually landed.

Compatibility

  • New optional field on a new tag — buf breaking against main passes.
  • Absent means last-writer-wins, which is the existing behavior, so already-queued intents and older clients are unaffected.
  • This message lives in the xmtp.mls.database package: it is local intent storage, never sent on the wire. Nothing about the MLS commit format changes.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AdY7WKkNbJmdzpmUWvW1my

Note

Add expected_field_value field to UpdateMetadataData.V1 proto message

Adds an optional string field expected_field_value (tag 3) to the UpdateMetadataData.V1 message in intents.proto. The field acts as a compare-and-swap guard, allowing callers to conditionally update metadata only when the current field value matches the expected value. The field is backward compatible and is omitted from the wire when not set.

Macroscope summarized 625e8c1.

@tylerhawkes
tylerhawkes requested a review from a team as a code owner August 19, 2026 17:55
@macroscopeapp

macroscopeapp Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 625e8c1

Macroscope's review found this PR approvable — Additive, backwards-compatible protobuf schema change - adding one optional field to an existing message. The author owns this file per CODEOWNERS, and the change is well-documented with clear intent.

Notes:

  • No code objects were reviewed. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

@tylerhawkes
tylerhawkes enabled auto-merge (squash) August 19, 2026 17:59
@tylerhawkes
tylerhawkes merged commit dedb872 into main Aug 19, 2026
7 checks passed
@tylerhawkes
tylerhawkes deleted the tyler/appdata-cas-expected-value branch August 19, 2026 17:59
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 3.96.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

tylerhawkes added a commit to xmtp/libxmtp that referenced this pull request Aug 19, 2026
…4018)

Regenerates the Rust protos to pick up
[xmtp/proto#343](xmtp/proto#343), which adds
`expected_field_value` to `UpdateMetadataData.V1` — the compare-and-swap
guard the metadata-update intent needs.

`UpdateMetadataData` lives in the `xmtp.mls.database` package: it is the
payload libxmtp stores for a queued intent, never sent on the wire.
Nothing about the MLS commit format changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants