Skip to content

feat(profiles): read v2 profile updates, carry avatar URL and version - #137

Open
yewreeka wants to merge 1 commit into
mainfrom
jarod/profile-update-v2
Open

feat(profiles): read v2 profile updates, carry avatar URL and version#137
yewreeka wants to merge 1 commit into
mainfrom
jarod/profile-update-v2

Conversation

@yewreeka

@yewreeka yewreeka commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

Companion to the iOS profiles stack (xmtplabs/convos-ios#1387). The iOS client now writes profiles to the Convos backend keyed by account and fans out convos.org/profile_update as a change signal — plain avatar URL plus the backend's version, no encrypted image — under content type v2.

Why this is needed

@xmtp/node-sdk keys its codec registry on the full content-type string, version included:

const contentTypeToString = (ct) => `${ct.authorityId}/${ct.typeId}:${ct.versionMajor}.${ct.versionMinor}`;

So a v2 message finds no codec, logs No codec found for content type, and arrives as raw EncodedContent. getProfileUpdateContent does fall back to decoding the protobuf by hand, so names keep working — but it is an accident, not a design, and it makes every profile update noisy.

What changes

  • ProfileUpdate gains avatar_url (5) and version (6). Field 2 (encrypted_image) stays declared, not reserved — un-upgraded senders still populate it, and reserving it would decode their avatar as absent rather than failing loudly.
  • ProfileUpdateV2Codec + ContentTypeProfileUpdateV2, registered alongside the existing codec.
  • version decodes through a Long and treats 0 as absent: protobufjs decodes an unset uint64 as 0, and backend versions start at 1.

What deliberately does not change

Sending stays on v1. The proto is a superset, so the new fields ride along on a v1-typed message and every client decodes them — including iOS, whose ProfileUpdateV1Codec decodes into the same generated type. Bumping the send version would make an agent's name updates invisible to every client older than the v2 release, and buys nothing: agent avatars were already plain URLs, so the CLI has no encrypted-image break to announce. The iOS client bumps because it genuinely stopped sending images; the CLI has not.

Testing

npm run typecheck clean; 448 unit tests pass, including round-trips for the new fields, the v1-payload read, and a check that encoding still emits v1.

Follow-up

herald-lite should surface avatarUrl/version on its profile_update webhook — blocked until this ships to npm and the catalog version moves off 0.10.15.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Note

Add ProfileUpdateV2Codec and carry avatarUrl and version in profile updates

  • Extends the ProfileUpdate protobuf with optional avatar_url (tag 5) and version (uint64, tag 6) fields in profileMessages.ts
  • Introduces ContentTypeProfileUpdateV2 and ProfileUpdateV2Codec, which reuses v1 encode/decode logic but registers under the v2 content type
  • Registers ProfileUpdateV2Codec in buildClient and re-exports it from the package entrypoint so consumers can import it
  • encodeProfileUpdate still emits the v1 content type but now populates the new fields when provided; decodeProfileUpdate surfaces avatarUrl and ignores zero/unset version
  • Behavioral Change: v1 profile update messages now carry avatar_url and version on the wire when set; receivers without the updated codec will ignore these unknown protobuf fields
📊 Macroscope summarized c46362a. 3 files reviewed, 1 issue evaluated, 0 issues filtered, 1 comment posted

🗂️ Filtered Issues

The iOS client now writes profiles to the backend and fans out a
`profile_update` carrying a plain avatar URL and a version instead of an
encrypted image, under content type v2. The XMTP codec registry keys on
the full version string, so without a registered v2 codec those messages
arrive as raw EncodedContent and herald stops seeing avatars.

Sending stays on v1 on purpose. The proto is a superset, so the new
fields ride along on a v1-typed message and every client decodes them;
bumping the send version would instead make an agent's name updates
invisible to every client that predates v2, in exchange for nothing the
CLI has to advertise - agent avatars were already plain URLs.
memberKind?: MemberKind;
metadata?: ProfileMetadata;
/** Plain CDN URL of the backend-hosted avatar. */
avatarUrl?: string;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium utils/profileMessages.ts:143

resolveProfilesFromMessages drops avatarUrl and version from every decoded ProfileUpdate, so v2 profile updates resolve without the backend avatar or version. Add these fields to ResolvedProfile and propagate them through both update and snapshot resolution (mapping avatarUrl to image if that is the intended API).

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file @src/utils/profileMessages.ts around line 143:

`resolveProfilesFromMessages` drops `avatarUrl` and `version` from every decoded `ProfileUpdate`, so v2 profile updates resolve without the backend avatar or version. Add these fields to `ResolvedProfile` and propagate them through both update and snapshot resolution (mapping `avatarUrl` to `image` if that is the intended API).

@macroscopeapp

macroscopeapp Bot commented Aug 21, 2026

Copy link
Copy Markdown

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces new v2 profile update reading capability with new fields (avatarUrl, version). The Medium-severity finding identifies that these new fields are not propagated through resolveProfilesFromMessages, indicating incomplete implementation. New feature additions warrant human review.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

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