Skip to content

Align Go and Python prekey publish operation IDs with payload semantics#55

Merged
chgaowei merged 1 commit into
masterfrom
fix/prekey-publish-opid-go-python
Jul 20, 2026
Merged

Align Go and Python prekey publish operation IDs with payload semantics#55
chgaowei merged 1 commit into
masterfrom
fix/prekey-publish-opid-go-python

Conversation

@chgaowei

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #54, which made the Rust prekey-bundle publish helper require an explicit operation_id. This PR applies the same protocol rule — a publish operation_id identifies the complete publish payload, not only the stable bundle_id — to the Go and Python SDKs.

  • Go: PrekeyManager.PublishPrekeyBundle now derives the operation_id from the complete payload it assembles: op-publish-{bundle_id} for a bundle-only body, or op-publish-{bundle_id}-opks-{digest} when an OPK sidecar is present (digest = first 4 bytes of SHA-256 over the sorted OPK key IDs). The OPK sidecar comes from the manager's store, so callers cannot supply a payload-identifying ID themselves; deriving it inside the manager keeps exact retries idempotent while a replenished OPK sidecar gets a fresh ID and no longer trips the server's anp.idempotency_conflict (per the idempotency rules in message/05-direct-end-to-end-encryption.md).
  • Python: PrekeyManager.publish_prekey_bundle now requires an explicit operation_id parameter, mirroring the Rust change in Require explicit operation IDs for prekey bundle publication #54. Internal callers (ensure_fresh_prekey_bundle, client) pass op-publish-{bundle_id}, which identifies the bundle-only payload (the Python publish body carries no OPK sidecar).
  • Java / TypeScript / Dart have no prekey-publish code paths; nothing to change.

Compatibility

  • Go: no API change; only the derived operation_id value changes when an OPK sidecar is present.
  • Python: intentionally breaking, same as the Rust change in Require explicit operation IDs for prekey bundle publication #54publish_prekey_bundle(bundle, operation_id) requires the new argument.
  • Wire protocol fields are unchanged.

Validation

  • go vet ./direct_e2ee/ and go test ./direct_e2ee/ -count=1 — pass, including a new test covering bundle-only / retry-reuse / OPK-replenishment operation ID behavior.
  • pytest anp/unittest/direct_e2ee/ — 4 passed, including a new test that the explicit operation_id flows through and that ensure_fresh_prekey_bundle derives op-publish-{bundle_id}.

Pre-existing issues observed (not caused by this change)

  • TestSkippedMessageKeySurvivesFailedAuthentication (Go) is flaky on master; it passes on rerun.
  • go run ./examples/direct_e2ee fails on master with missing field: service during client construction, before any publish call.

Go derives the publish operation ID from the complete payload: the stable
bundle ID plus a digest of the sorted OPK sidecar key IDs, so exact retries
reuse the ID while a replenished OPK sidecar produces a new one instead of
tripping the server idempotency check.

Python now requires an explicit operation_id in
PrekeyManager.publish_prekey_bundle, mirroring the Rust helper change in #54;
internal callers pass op-publish-<bundle_id>, which identifies the
bundle-only payload.
@chgaowei
chgaowei merged commit e5baebb into master Jul 20, 2026
8 checks passed
@chgaowei
chgaowei deleted the fix/prekey-publish-opid-go-python branch July 20, 2026 11:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant