Repository navigation
Releases
0.25.0
Synced to flipcash2-protobuf-api@53316c0e,
picking up #165.
activity.v1, intent.v1 and messaging.v1 moved.
This release lets the receiver of a DM's opening payment send it back. Nothing existing changed
on the wire. The source breaks are three new oneof cases, each appended after the existing ones.
Breaking
activity.v1.DirectlySentCryptoNotificationMetadataandReceivedCryptoNotificationMetadata
each gainreturned_payment(field 5) in their oneof, andintent.v1.ChatMetadata's oneof
gainsreturn_payment(field 7). An exhaustiveswitchover the Swift oneof, or awhenover
Kotlin's*Casewithout anelse, needs a case for each before it compiles. Code that reads
these oneofs throughhas*()checks compiles unchanged and drops the new case silently.
Added
messaging.v1.Messaging.GetCashMessageReturnStatus, with its request and response.
ResultisOK,DENIED,NOT_FOUND(0–2) andStatusisUNKNOWN,AVAILABLE,
RETURNED(0–2).RETURNEDnever changes again, so a client can stop polling once it sees
it.payment_intent_idis set only onOK, and only for the message'ssingle_receiver.messaging.v1.CashContent.payment_return(field 7), of typeCashContent.Returnwith
independentofferandreturn_of.Return.Offeris empty: its presence is the offer.
Today only the cash message that opened a DM carries one. A message withreturn_ofset
returns the payment of the message it names, so a client that sees it can stop offering a
return on that message.intent.v1.ChatMetadata.ReturnPayment(message_id). The return is aSendPublicPayment
from the original message'ssingle_receiverback to its sender, in the same DM, for the
same currency, mint and native amount. Its intent ID must be the server-issued
payment_intent_idfromGetCashMessageReturnStatus, not one the client generates. The
server refuses any other ID, which is what keeps a payment returnable once across retries
and devices. Treat that ID as private until the payment is made: anyone who uses it first
blocks the return.activity.v1.ReturnedPayment(chat_id,message_id), naming the DM and the cash message
whose payment was returned. The server doesn't update it afterwards, so the message may since
have been deleted.
Unchanged
Nothing was renumbered. No service, RPC, field or enum case was removed or changed type.
0.24.0
Synced to flipcash2-protobuf-api@0e167fa6,
picking up #164. Only
chat.v1 moved.
This release adds pinned messages to chats. Nothing existing changed on the wire. The one
source break is a new oneof case, appended like every other addition here.
Breaking
chat.v1.MetadataUpdate'skindoneof gainspins_changed(field 9). An exhaustiveswitch
over the Swift oneof, or awhenover Kotlin'sKindCasewithout anelse, needs a case for
it before it compiles. Awhenwith anelsecompiles but routes pin events into that
branch, so check what it does.
Added
chat.v1.Chat.PinMessage,UnpinMessageandGetPinnedMessages, with their request and
response messages.PinMessageResponse.ResultisOK,DENIED,NOT_FOUND,
MESSAGE_NOT_FOUND,TOO_MANY_PINS,MESSAGE_NOT_ALLOWED(0–5); the other two results are
OK,DENIED,NOT_FOUND(0–2). Pin and unpin are no-ops returningOKwhen nothing would
change, and both return the chat'sPinSummaryonOK. The server caps a chat's pins (5
today) and may raise the cap, so clients must not hardcode it.chat.v1.Pin(message_id,pinned_by,pinned_at,message) andchat.v1.PinSummary
(latest,count,version).versionmoves by one on every real pin or unpin and is
compared likeRosterSummary.version: keep the greater.chat.v1.Metadata.pin_summary(field 19). It may be unset on feed RPCs such as
GetDmChatFeedandGetGroupChatFeed, and an unset value there must not clear a summary the
client already holds.chat.v1.MetadataUpdate.PinsChanged, withpinnedorunpinnedand the summary after the
change.chat.v1.ViewerState.Permissions.can_pin(field 4). Today it is true for either member of a
DM and for a group's creator while they are a member.
Unchanged
Nothing was renumbered. No service, RPC, field or enum case was removed or changed type.
0.23.0
Synced to flipcash2-protobuf-api@6de4f9ad,
picking up #160,
#161,
#162 and
#163. activity.v1,
chat.v1, event.v1, paymentrequest.v1 and push.v1 moved.
This release makes a public group's minimum balances editable, announces payment request changes
on the chat event stream, links feed payments to the payment request they paid, and adds a test
push. Upgrading breaks source in Swift only, not the wire. One enum gained cases, appended at the
end, so no existing value moved.
Breaking
activity.v1.DirectlySentCryptoNotificationMetadata.boosted_reactionand
ReceivedCryptoNotificationMetadata.boosted_reaction(field 3 in both) moved into a new
oneof context, next torequested_payment. Swift loseshasBoostedReactionand
clearBoostedReactionon both; switch oncontextinstead. Kotlin keepshasBoostedReaction()
and gainsgetContextCase().chat.v1.MetadataUpdate'skindoneof gainsrules_changed(field 8). An exhaustiveswitch
over the Swift oneof, or awhenover Kotlin'sKindCasewithout anelse, needs a case for
it before it compiles.
Added
activity.v1.RequestedPayment, withchat_idandpayment_request_id, set as
requested_payment(oneof field 4) on both notification metadata messages above when the
payment paid a share of a payment request. It records what the payment was for and is not kept
up to date: the request may have closed, and fetching it may be denied.chat.v1.EditChatRequest.rules(field 6), the group's rules in full. Only a public group created
with a listener minimum balance can be edited, and only its listener and speaker
MinimumBalanceRequirementamounts may change; the proto docs list the limits.EditChatResponse.ResultcasesINVALID_RULES = 7andRULES_NOT_SATISFIED = 8, both
appended.chat.v1.MetadataUpdate.RulesChanged, carryingnew_rulesin full, sent on every rules edit.event.v1.ChatUpdate.payment_request_updates(field 10), a
paymentrequest.v1.PaymentRequestUpdateBatch. Like reaction updates, it is best effort and not
part of the gap-detected event log.paymentrequest.v1.PaymentRequestUpdate: a request whole when it is created (created), then
each change asUpdatesat the version it produced, made ofSharePaymentUpdateand
StatusUpdate. The proto docs give the apply rules: ignore a version already held, apply the
next one, and refetch on a gap or on an update the client cannot apply. Expiry is never
announced.push.v1.Push.SendTestPush, withSendTestPushRequestandSendTestPushResponse. It sends a
fixed notification to every device the caller registered a token for.
Changed
- A public group's
Metadata.rulescan now change after creation. A member who no longer
satisfies the new listener rules stays a member but cannot speak until they do. - Payment request changes are announced in real time. Until now the docs told clients to refetch
a request to see payments and closes land; refetching is now only for reconciling a missed
update.
Unchanged
Nothing was renumbered. No service, RPC, field or enum case was removed. Apart from the oneof
move above, no field changed type or number.
0.22.0
Synced to flipcash2-protobuf-api@b655df17,
picking up #157,
#158 and
#159. chat.v1,
messaging.v1 and common.v1 moved.
This release adds invite links for private groups, plus anonymous reads of an invite and the
chat's roster. Upgrading breaks source in Swift only, not the wire. One enum gained cases,
appended at the end, so no existing value moved.
Breaking
chat.v1.GetKeyEnvelopeResponse.key_envelope(field 2) moved into a newoneof envelope, next
toinvite_key_bundle. Swift loseshasKeyEnvelopeandclearKeyEnvelope; switch on
envelopeinstead. Kotlin keepshasKeyEnvelope()and gainsgetEnvelopeCase(). In either
language, a client that reads onlykey_envelopesees an empty envelope for a member who joined
with an invite.common.v1.Usernamenow accepts 2 to 30 characters, up from 15. Nothing fails to compile, but a
client that validates, matches or encodes usernames at 15 will reject or truncate names the
server now issues.
Added
- Invite RPCs on
chat.v1.Chat:CreateInvite,GetInvite,GetChatInvitesand
RevokeInvite, withInvite,Invite.Status,InviteId,InviteToken,InviteKeyEnvelope
andInviteSecretEnvelope. Only a private group's creator may create, list or revoke invites
today.GetInvitetakes optionalauth, so a link can be previewed without an account. - The
Invitedocs specify the client-side crypto: how the token, wrap key and invite ID derive
from the link's secret (HKDF-SHA256 and SHA-256), the XChaCha20-Poly1305 encryption of the
chat key, and the creator's Ed25519 signature over it. iOS and Android must compute these
identically. JoinChatRequest.invite(field 2), anInviteParameterswith the invite token and the joiner's
InviteSecretEnvelope. A private group can now be joined with an invite.JoinChatResponse.ResultcasesINVITE_NOT_FOUND = 5,INVITE_EXHAUSTED = 6,
INVITE_EXPIRED = 7andINVITE_REVOKED = 8, all appended. An exhaustiveswitchorwhen
over the result needs them before it compiles.GetKeyEnvelopeResponse.invite_key_bundle(oneof field 5), returned instead ofkey_envelope
to a member who joined with an invite and has not yet stored their own envelope with
SetKeyEnvelope.GetKeyEnvelopeResponse.wrapped_by_public_key(field 4).GetRosterRequest.invite_token(field 3). A link holder can read the roster with it.chat.v1.ViewerState.Permissions.can_invite(field 3).messaging.v1.SystemContentmember-joined oneof gainsinvited(field 4), anInvitednaming
invited_by. A client that renders join messages needs a case for it.
Changed
GetRosterRequest.authis no longer required wheninvite_tokenis set. A request with
neither is stillDENIED.GetChaton a private group without auth now returns itsMetadatarecord instead of
DENIED. Its messaging state stays private.JoinChaton a private group by anyone but the creator is no longer alwaysDENIED: it
succeeds with anACTIVEinvite. An invite join also removes the user from the lobby and is
announced asRosterUpdate.MemberJoined, like an admission.
Unchanged
Nothing was renumbered. No service, RPC, field or enum case was removed. Apart from the oneof
move above, no field changed type or number.
0.21.0
Synced to flipcash2-protobuf-api@b77bf78f,
picking up #151,
#152 (docs only),
#154 (docs only),
#155 and
#156. paymentrequest.v1 is
new. activity.v1, chat.v1, intent.v1 and messaging.v1 moved.
This release adds payment requests (group splits), payments to several group members at once, and
moderation RPCs for group creators. Upgrading breaks source, not the wire. CashContent renamed
two fields and moved one into a oneof, so code reading amount or receiver stops compiling. Two
enums gained a case, appended at the end, so no existing value moved.
Breaking
messaging.v1.CashContent.amount(field 2) is nowtotal_amount. Same type and number. For a
payment to several people it is the whole payment.messaging.v1.CashContent.receiver(field 3) is nowsingle_receiver, inside a new
oneof recipient. Kotlin'sgetReceiver()/hasReceiver()becomegetSingleReceiver()/
hasSingleReceiver(); Swift'sreceiverbecomessingleReceiver. An older DM message that
predates per-message receivers still has neither member of the oneof set.
The binary encoding of both fields is unchanged, so messages written before and after the rename
decode the same way.
Added
paymentrequest.v1.PaymentRequest, a new service with five RPCs:CreatePaymentRequest,
GetPaymentRequest,GetChatPaymentRequests,ClosePaymentRequestandMarkPaid. The one kind
today is a split in a group chat (GroupChatPaymentRequestwith aSplitof per-member
Shares). DMs are not supported. No event announces a change to a request; clients refetch it.- In a private group the split's title and description are
EncryptedPaymentRequestTextunder
the chat key. Everything else, including shares and payments, is visible to the server. GetPaymentRequestResponse.payment_intent_idis the intent ID a debtor's payment of their share
must use. The server issues one per share, so a share is paid at most once.
- In a private group the split's title and description are
messaging.v1.PaymentRequestWidget, sent asWidgetContent.payment_request(oneof field 3). It
carries only the request's ID.intent.v1.ChatMetadata.requested_payment(oneof field 6), aRequestedPaymentnaming the
payment_request_idwhose share aSendPublicPaymentpays.messaging.v1.CashContent.multi_receiver(oneof field 5), aPaymentslist of 2 to 10
Payment { receiver, native_amount, quarks }. A group payment to several members is an ocp
SendPublicMultiPayment.messaging.v1.CashContent.payment_request_id(field 6), set only on the cash message posted when
a debtor pays their share.- Chat moderation RPCs on
chat.v1.Chat:SilenceUser,UnsilenceUser,BanUser,UnbanUserand
GetRestrictedUsers, withSilenceState,BanStateandRestrictedUser. The chat's creator
cannot be silenced or banned. chat.v1.ViewerState.restrictions(field 3), carrying the viewer'ssilence. A timed silence
lapses with no event, so the client owns the countdown.chat.v1.ViewerState.Permissions.moderation(field 2), aModerationPermissionswith
can_silenceandcan_ban.JoinChatResponse.Result.BANNED = 4andEnterLobbyResponse.Result.BANNED = 6, both appended.
An exhaustiveswitchorwhenover either needs the new case before it compiles.
Changed
- Reaction boosts are now allowed in DMs. A DM boost pays the other member the whole amount as one
SendPublicPayment. No field changed; theactivity.v1.BoostedReactionand
intent.v1.ChatMetadata.ReactionBoostdocs now cover DMs. SendMessageandEditMessagedocument thatENCRYPTION_REQUIREDalso applies to DMs.
Unchanged
Nothing was renumbered. No service, RPC or enum case was removed. Apart from the CashContent
rename above, no field was removed or changed type.
0.20.0
Synced to flipcash2-protobuf-api@733ea7f9,
picking up #147,
#148 and
#149 (docs only). community.v1
is new. activity.v1, chat.v1, intent.v1 and messaging.v1 moved.
This release adds the Community service, paid reaction boosts and a holdings summary on gated group
chats. Everything is additive. Two enums gained a case, appended at the end, so no existing value
moved. An exhaustive switch or when over either enum needs the new case before it compiles.
Added
community.v1.Community, a new service with one RPC,GetCommunity. It looks a community up by
mintand returnsCommunityMetadata(mint,name,leader, and up to 25
top_holder_chats), orNOT_FOUND.- Reaction boosts. A payer puts money behind a reaction they already hold on a group message:
intent.v1.ChatMetadata.reaction_boost(oneof field 5), aReactionBoostnaming the
message_idandemoji.- A boost that pays two people, the sender and the group's creator split 80/20, is an ocp
SendPublicMultiPayment, so it needsocp-client-protocol0.8.0 or later. A boost that pays
one person is aSendPublicPayment. messaging.v1.Reactor.boost_usd(field 4),EmojiReaction.boost_usd(field 6),
ReactionUpdate.boost_usd(field 8) andReactionUpdate.actor_boost_usd(field 9).ReactionUpdate.Action.BOOSTED = 3.RemoveReactionResponse.Result.CANNOT_REMOVE_BOOSTED = 3. A boosted reaction is permanent.activity.v1.BoostedReaction, set asboosted_reaction(field 3) on both
DirectlySentCryptoNotificationMetadataandReceivedCryptoNotificationMetadatawhen the
payment was a boost.
chat.v1.Metadata.holdings_summary(field 18), aHoldingsSummaryof the group members' holdings
of the currency the group is gated on (mint,quarks,holder_count,as_of). It is set only
for public groups gated on a single Flipcash-launched currency with enough holders. It is a
periodic snapshot, and no event announces a change.
Changed
- Reactor lists,
sample_reactorsandReactionSummary.reactionsnow sort boosted entries first,
byboost_usddescending, then fall back to the previous order. Nothing changed on the wire, but
a client that re-sorts byversionalone will disagree with the server. GetReactorsnow documents that a paging token the server no longer recognises, such as one
issued under the old order, is answered with the first page rather than an error. Don't keep
tokens across sessions.
Unchanged
Nothing was renumbered. No service, RPC, message, field or enum case was removed or changed type.
0.19.0
Synced to flipcash2-protobuf-api@1897108a,
picking up #139 (docs only),
#140,
#141,
#142,
#143,
#144,
#145 and
#146. poll.v1 is new;
intent.v1 and messaging.v1 moved; chat.v1 changed only in comments.
This release adds polls, payments in group chats, link previews and structured system messages. One
enum moved, which is wire-compatible but breaks source in both languages.
Moved
ChatMetadata.DmPayment.Actionis now the top-level enumPaymentAction, shared by DM and
group payments. Its cases keep their values (DEFAULT = 0,SEND = 1,TIP = 2) and
DmPayment.actionkeeps field 2, so the wire format is unchanged. Code naming the old type has
to be updated:Flipcash_Intent_V1_ChatMetadata.DmPayment.Actionbecomes
Flipcash_Intent_V1_PaymentActionin Swift, andChatMetadata.DmPayment.Actionbecomes
PaymentActionin Kotlin.
Added
- A
Pollservice inpoll.v1withCreatePoll,GetPoll,GetPollsandVote, and its model:
count or balance-weighted polls of 2 to 10 options, single or multiple choice, a required end
time 5 minutes to 30 days out, and question text that is plaintext in a group that is not
private and encrypted in a private one. Results come back as count, balance, ranked or withheld,
and every vote result model carriestotal_voters. WidgetContent.poll(field 2), aPollWidgetcarrying only the poll's ID. In a group that is not
private,SendMessageaccepts it only from the poll's creator, in the poll's own chat, while the
poll isOPEN. A private group sends it insideEncryptedContent, where clients do those checks
and render a mismatch as unsupported.ChatMetadata.group_payment(field 4), aGroupPaymentfor paying another member of a group
chat. The payment's destination owner names the recipient, who must be a member. OnlyDEFAULT
andSENDare accepted; the server deniesTIP.CashContent.receiver(field 3, previously reserved), the user who received the cash. It is
always set in a group chat. In a DM it is set on new messages only, so a client reading older DM
messages still has to treat the other member as the receiver when it is unset.TextContent.link_previews(field 2), at most oneLinkPreviewwith aurl,title, optional
descriptionand optionalimage. The sending device builds the preview, so its title,
description and image are the sender's claim; the comments onLinkPreviewspell out the
validation rules and how clients have to render the host.SystemContent.type, a required oneof whose first case isuser_joined(field 2).UserJoined
names the user and how they joined:direct, oradmittedwith the user who let them in.
fallback_textis unchanged and still always set; a client renders it only for a variant it
does not recognize.
Changed
EncryptedContent.ciphertextmay now be up to 28672 bytes, up from 17408, to fit a maximum-length
text with a link preview.
Unchanged
Nothing was renumbered. Every result enum in this release is new, so no existing case moved. Apart
from the PaymentAction move, no existing field changed type or meaning, and no service, RPC,
message or enum case was removed.
0.18.0
Synced to flipcash2-protobuf-api@9d44350b,
picking up #135,
#136,
#137 and
#138. Only chat.v1 moved;
blob.v1 changed only in comments.
Renumbered
EditChatResponse.Result:COVER_PICTURE_BLOB_NOT_ACCEPTEDis inserted at 5, and
DESCRIPTION_MODERATEDmoves from 5 to 6. 0.17.0 shippedDESCRIPTION_MODERATED = 5, so a
0.17.0 client reads a cover-picture rejection from a current server as a moderated description,
and does not recognize 6 at all. Code that maps this enum by raw value, such as iOS's
Error*(rawValue:), has to be re-checked case by case, not only extended.
No other field or enum moved. StartChatResponse.Result gains its new case at the end.
Renamed
The group picture becomes the profile picture, to tell it apart from the new cover picture. Field
numbers are unchanged, so this is wire-compatible but breaks source in both languages.
Metadata.picture→profile_picture(= 9).picture→profile_picture(= 2) onPublicGroupChatParametersand
PrivateGroupChatParameters.EditChatRequest.picture→profile_picture(= 3), and its typePicture→ProfilePicture.MetadataUpdate.picture_changed→profile_picture_changed(= 5), andPictureChanged→
ProfilePictureChangedwithnew_picture→new_profile_picture.PICTURE_BLOB_NOT_ACCEPTED→PROFILE_PICTURE_BLOB_NOT_ACCEPTEDonStartChatResponse.Result
(= 3) andEditChatResponse.Result(= 4).
Added
- Group cover pictures, the banner behind a chat's profile view.
Metadata.cover_picture(= 17). The feed RPCs may leave it unset even when one is set, so a
feed result must not clear a cover picture the client already holds;GetChatreturns it.- Set at creation through
cover_pictureonPublicGroupChatParameters(= 5) and
PrivateGroupChatParameters(= 4), and changed throughEditChatRequest.cover_picture
(= 5, aCoverPicture { blob_id }wrapper). - Announced as
MetadataUpdate.CoverPictureChanged(= 7,new_cover_picture). COVER_PICTURE_BLOB_NOT_ACCEPTEDonStartChatResponse.Result(= 7) and
EditChatResponse.Result(= 5, see above).
RosterUpdate.MembershipChanged(= 3), an empty case for a roster change the recipient is not
shown. Apply itsroster_summaryby version and leave the cached member list alone.Chat.SampleChatters, a public sample of up to 100 members of a public group: its creator, then
the most recent senders. Auth is optional. ReturnsSampledChatter(user_profile,
last_sent_at,is_creator) andhas_more.Chat.SetFeaturedGroupsandChat.GetFeaturedGroups, an ordered list of up to 10 public groups a
user shows on their profile.GetFeaturedGroupslooks the user up byusername, takes optional
auth, and returns each group as a list view shows it, withoutcover_pictureor any viewer or
messaging state.
Changed behavior
GetRosternow requires membership. A non-member whom a group's listener rules let read its
messages used to get the roster and now getsDENIED.SampleChattersis the public
alternative.
Upgrading
Expect compile errors from the renames. Beyond those, an exhaustive MetadataUpdate switch needs
CoverPictureChanged, an exhaustive RosterUpdate switch needs MembershipChanged, and anything
that calls GetRoster for a group the user has not joined needs to stop.
0.17.0
Synced to flipcash2-protobuf-api@3bb442d3,
picking up #134. Only chat.v1
moved.
Added
- Group descriptions, up to 160 characters and moderated like the title.
chat.v1.Metadata.description(= 16).- Set at creation through
descriptiononPublicGroupChatParameters(= 4) and
PrivateGroupChatParameters(= 3). Optional; empty sets none. - Changed through
EditChatRequest.description(= 4), aDescription { value }wrapper: unset
leaves the description alone, and a set wrapper with an emptyvalueclears it. - Announced as
MetadataUpdate.DescriptionChanged(= 6,new_description).
DESCRIPTION_MODERATEDonStartChatResponse.Result(= 6) andEditChatResponse.Result(= 5).
The response'sflagged_categoryis set for it, as it is forTITLE_MODERATED.
Upgrading
Nothing existing changed: no renames, and no field or enum renumbering. Both new result cases come
after the existing ones. A client that ignores description keeps working, but one with an
exhaustive MetadataUpdate switch needs a DescriptionChanged case.
0.16.0
Synced to flipcash2-protobuf-api@ec66e6b1,
picking up #132 and
#133. chat.v1, event.v1,
messaging.v1 and profile.v1 moved; blob.v1 changed only in comments.
Changed
StartChatRequest'sgrouponeof case is nowpublic_group, and its message
GroupChatParametersis nowPublicGroupChatParameters. The field number is still 1, so this is
wire-compatible, but every call site that sets or reads it stops compiling on upgrade
(setGroup/groupin Kotlin,.groupin Swift).
Added
- Private groups.
StartChatRequestgains aprivate_groupcase (= 2) with
PrivateGroupChatParameters(title, 1–64 characters; optionalpicture). A private group is
visible once created, but nothing can happen in it until its creator stores the group's key. - Seven
ChatRPCs for the lobby and keys:EnterLobby,LeaveLobby,GetLobbyMembers,
AdmitLobbyMember,DenyLobbyMember,SetKeyEnvelopeandGetKeyEnvelope, each with its own
Resultenum. A user waits in the lobby until the creator admits or denies them; admitting is
the only way to hand another user a key envelope, and the admission arrives as an ordinary
RosterUpdate.MemberJoined. A denial is not announced to the denied user. chat.v1.KeyEnvelope(scheme, 24-bytenonce, 48-byteciphertext): the group's 32-byte chat
key, wrapped per member. The first envelope a caller stores for themself stands; a different one
afterwards returnsALREADY_SET. There is no forward secrecy, and a member who leaves still knows
the chat key.chat.v1.Lobby,LobbyMember,LobbyUpdateandLobbyUpdateBatch, and
event.v1.ChatUpdate.lobby_updates(= 9) carrying members entering and leaving a lobby.chat.v1.Metadata.is_private(= 14) andin_lobby(= 15).in_lobbyis per-viewer: there is no
RPC that lists the lobbies a caller is waiting in, so a client reads it fromGetChat.messaging.v1.EncryptedContent.Scheme.CHAT_KEY_XCHACHA20POLY1305(= 2), the scheme private groups
use. Clients render a scheme they don't recognize as unsupported.ENCRYPTION_REQUIREDonSendMessageResponse.Result(= 3) andEditMessageResponse.Result
(= 6): the chat is a private group and the content is notEncryptedContent.- Profile bios and cover pictures:
UserProfile.bio(= 12, up to 160 characters) and
cover_picture(= 13), set through the newProfile.SetBioandProfile.SetCoverPictureRPCs.
SetBiocan come backFAILED_MODERATEDwith aflagged_category;SetCoverPicturereports blob
state the same waySetProfilePicturedoes.
Upgrading
The public_group rename is the one source break. No field or enum value was renumbered: every new
enum case is appended after the existing ones, so Error*(rawValue:) mappings keep their meaning.