Skip to content

feat: wire up --profile-image and --metadata flags on conversations join#17

Open
yewreeka wants to merge 1 commit intomainfrom
feature/join-profile-fields
Open

feat: wire up --profile-image and --metadata flags on conversations join#17
yewreeka wants to merge 1 commit intomainfrom
feature/join-profile-fields

Conversation

@yewreeka
Copy link
Collaborator

@yewreeka yewreeka commented Mar 13, 2026

Summary

The join request protocol already supported imageURL and metadata fields in JoinRequestContent, but they were not exposed via CLI flags. This wires them up.

New flags on convos conversations join

Flag Description
--profile-image <url> Profile image URL — sent in the JoinRequest and encrypted/uploaded as a ProfileUpdate after joining
--metadata <key=value> Custom metadata — sent in the JoinRequest and included as typed metadata in the ProfileUpdate. Repeatable. Auto-typed: true/false → bool, numeric → number, else string

How it works

Both fields flow through two stages:

  1. JoinRequest DM — the creator sees the joiner's full profile (name, image, metadata) when processing join requests
  2. Post-join ProfileUpdate — after being added to the group, a ProfileUpdate message is sent with the encrypted image and typed metadata, making the profile visible to all group members

Examples

# Join with name and avatar
convos conversations join <slug> --profile-name "Bot" --profile-image "https://example.com/avatar.jpg"

# Join with metadata
convos conversations join <slug> --metadata role=assistant --metadata version=2

# All together
convos conversations join <slug> \
  --profile-name "Agent" \
  --profile-image "https://example.com/bot.png" \
  --metadata role=assistant \
  --metadata capabilities=search,summarize

Image encryption

When --profile-image is provided and the join is accepted, the image is:

  1. Downloaded from the URL
  2. Encrypted using the group's image encryption key (HKDF-SHA256 + AES-256-GCM)
  3. Uploaded via the configured upload provider
  4. Sent as an EncryptedProfileImageRef in the ProfileUpdate

If no upload provider is configured, a warning is shown and the image is skipped (non-fatal).

Version

Bumped to 0.5.2. All 226 tests pass.

Note

Wire up --profile-image and --metadata flags on conversations join

  • Adds --profile-image <url> and --metadata <key=value> (repeatable) flags to the conversations join command in join.ts.
  • Join requests sent via DM now include profile.imageURL and a typed metadata map when the flags are provided; values are auto-typed to bool, number, or string.
  • On successful join, sends a ProfileUpdate with name, metadata, and an optionally encrypted/uploaded profile image using a per-conversation imageEncryptionKey stored in conversation appData.
  • JSON output for both --no-wait and final success paths includes profileImage and metadata fields when provided.
  • Risk: image upload is silently skipped with a warning if no upload provider is configured or if encryption/upload fails.
📊 Macroscope summarized 39dc48b. 1 file reviewed, 2 issues evaluated, 0 issues filtered, 1 comment posted

🗂️ Filtered Issues

The join request protocol already supported imageURL and metadata fields
but they were not exposed via CLI flags. Now when joining a conversation:

- --profile-image <url>: sends image URL in the JoinRequest and encrypts/
  uploads it as a ProfileUpdate after joining
- --metadata key=value: sends metadata in the JoinRequest and includes
  typed metadata in the ProfileUpdate (auto-typed: bool/number/string).
  Repeatable for multiple fields.

Both fields are included in the JoinRequest DM (so the creator can see
who's requesting to join) and in the post-join ProfileUpdate message
(the authoritative profile source for the group).

Bumps version to 0.5.2.
const uploadProvider = getUploadProvider(config);
if (uploadProvider) {
// Get or generate the group's image encryption key
await conv.sync();
Copy link

Choose a reason for hiding this comment

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

🟢 Low conversations/join.ts:329

When multiple clients join simultaneously with --profile-image, each independently checks for the group image encryption key and may generate a new one, causing the last writer to overwrite earlier keys. The clients whose keys were overwritten cannot decrypt their own images because they were encrypted with a key that no longer exists. This contradicts the stated intent in lines 305-308 of avoiding read-modify-write races. Consider adding atomic key generation or recovering the existing key from the updated appData after another client writes it.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file src/commands/conversations/join.ts around line 329:

When multiple clients join simultaneously with `--profile-image`, each independently checks for the group image encryption key and may generate a new one, causing the last writer to overwrite earlier keys. The clients whose keys were overwritten cannot decrypt their own images because they were encrypted with a key that no longer exists. This contradicts the stated intent in lines 305-308 of avoiding read-modify-write races. Consider adding atomic key generation or recovering the existing key from the updated appData after another client writes it.

Evidence trail:
src/commands/conversations/join.ts lines 305-308 (comment about avoiding read-modify-write race), lines 329-339 (the read-modify-write pattern for imageEncryptionKey: sync at 329, read appData at 330-331, check key at 332, generate and write at 334-337), lines 340-350 (encrypt image with the generated key)

@macroscopeapp
Copy link

macroscopeapp bot commented Mar 13, 2026

Approvability

Verdict: Needs human review

This PR introduces new --profile-image and --metadata flags with substantial new logic including metadata auto-typing, image encryption, and upload integration. The new capability and complexity of the encryption/upload workflow warrants human review.

You can customize Macroscope's approvability policy. 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