Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,52 @@ called out explicitly even when nothing else did.
release notes, so a version with no entry here does not release. Write the entry in the same PR that
syncs the contract, while the diff is still in front of you.

## 0.16.0

Synced to [`flipcash2-protobuf-api@ec66e6b1`](https://github.com/code-payments/flipcash2-protobuf-api/commit/ec66e6b12c59d7eae3281341e74fe8853c90a306),
picking up [#132](https://github.com/code-payments/flipcash2-protobuf-api/pull/132) and
[#133](https://github.com/code-payments/flipcash2-protobuf-api/pull/133). `chat.v1`, `event.v1`,
`messaging.v1` and `profile.v1` moved; `blob.v1` changed only in comments.

### Changed

- `StartChatRequest`'s `group` oneof case is now `public_group`, and its message
`GroupChatParameters` is now `PublicGroupChatParameters`. 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`/`group` in Kotlin, `.group` in Swift).

### Added

- Private groups. `StartChatRequest` gains a `private_group` case (= 2) with
`PrivateGroupChatParameters` (`title`, 1–64 characters; optional `picture`). A private group is
visible once created, but nothing can happen in it until its creator stores the group's key.
- Seven `Chat` RPCs for the lobby and keys: `EnterLobby`, `LeaveLobby`, `GetLobbyMembers`,
`AdmitLobbyMember`, `DenyLobbyMember`, `SetKeyEnvelope` and `GetKeyEnvelope`, each with its own
`Result` enum. 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-byte `nonce`, 48-byte `ciphertext`): the group's 32-byte chat
key, wrapped per member. The first envelope a caller stores for themself stands; a different one
afterwards returns `ALREADY_SET`. There is no forward secrecy, and a member who leaves still knows
the chat key.
- `chat.v1.Lobby`, `LobbyMember`, `LobbyUpdate` and `LobbyUpdateBatch`, and
`event.v1.ChatUpdate.lobby_updates` (= 9) carrying members entering and leaving a lobby.
- `chat.v1.Metadata.is_private` (= 14) and `in_lobby` (= 15). `in_lobby` is per-viewer: there is no
RPC that lists the lobbies a caller is waiting in, so a client reads it from `GetChat`.
- `messaging.v1.EncryptedContent.Scheme.CHAT_KEY_XCHACHA20POLY1305` (= 2), the scheme private groups
use. Clients render a scheme they don't recognize as unsupported.
- `ENCRYPTION_REQUIRED` on `SendMessageResponse.Result` (= 3) and `EditMessageResponse.Result`
(= 6): the chat is a private group and the content is not `EncryptedContent`.
- Profile bios and cover pictures: `UserProfile.bio` (= 12, up to 160 characters) and
`cover_picture` (= 13), set through the new `Profile.SetBio` and `Profile.SetCoverPicture` RPCs.
`SetBio` can come back `FAILED_MODERATED` with a `flagged_category`; `SetCoverPicture` reports blob
state the same way `SetProfilePicture` does.

### 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.

## 0.15.0

Synced to [`flipcash2-protobuf-api@993127b5`](https://github.com/code-payments/flipcash2-protobuf-api/commit/993127b50e42046ee2f290f122b05625774a0661),
Expand Down
4 changes: 2 additions & 2 deletions Sources/Flipcash2ClientProtocol/ContractInfo.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Generated by scripts/generate-swift.sh. Do not edit.

public enum Flipcash2ContractInfo {
public static let version = "0.15.0-dev"
public static let protoCommit = "993127b50e42046ee2f290f122b05625774a0661"
public static let version = "0.16.0-dev"
public static let protoCommit = "ec66e6b12c59d7eae3281341e74fe8853c90a306"

public static var isLocal: Bool { protoCommit == localSentinel }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,13 +136,16 @@ public struct Flipcash_Blob_V1_InitiateExternalUploadRequest: Sendable {
/// profile or chat pictures).
public var endToEndEncryptedFor: Flipcash_Blob_V1_InitiateExternalUploadRequest.OneOf_EndToEndEncryptedFor? = nil

/// The bytes are encrypted for this DM, as described in
/// messaging.v1.EncryptedContent: the 24-byte nonce followed by the
/// The bytes are encrypted for this DM or private group, as described
/// in messaging.v1.EncryptedContent: the 24-byte nonce followed by the
/// ciphertext and its 16-byte tag. The caller must be a member of the
/// chat and the chat must be a DM, or the upload is DENIED. Once READY,
/// the blob is granted to the chat, so the other member can read it
/// through AccessContext.chat, and it can be referenced only from
/// EncryptedContent in that chat.
/// chat and the chat must be a DM or a private group
/// (chat.v1.Metadata.is_private), or the upload is DENIED. So is an
/// upload for a private group whose creator has not stored its key
/// yet (see chat.v1.StartChatRequest.PrivateGroupChatParameters).
/// Once READY, the blob is granted to the chat, so its other members
/// can read it through AccessContext.chat, and it can be referenced
/// only from EncryptedContent in that chat.
public var chat: Flipcash_Common_V1_ChatId {
get {
if case .chat(let v)? = endToEndEncryptedFor {return v}
Expand All @@ -165,13 +168,16 @@ public struct Flipcash_Blob_V1_InitiateExternalUploadRequest: Sendable {
/// named here, and is rejected anywhere else (unencrypted MediaContent,
/// profile or chat pictures).
public enum OneOf_EndToEndEncryptedFor: Equatable, Sendable {
/// The bytes are encrypted for this DM, as described in
/// messaging.v1.EncryptedContent: the 24-byte nonce followed by the
/// The bytes are encrypted for this DM or private group, as described
/// in messaging.v1.EncryptedContent: the 24-byte nonce followed by the
/// ciphertext and its 16-byte tag. The caller must be a member of the
/// chat and the chat must be a DM, or the upload is DENIED. Once READY,
/// the blob is granted to the chat, so the other member can read it
/// through AccessContext.chat, and it can be referenced only from
/// EncryptedContent in that chat.
/// chat and the chat must be a DM or a private group
/// (chat.v1.Metadata.is_private), or the upload is DENIED. So is an
/// upload for a private group whose creator has not stored its key
/// yet (see chat.v1.StartChatRequest.PrivateGroupChatParameters).
/// Once READY, the blob is granted to the chat, so its other members
/// can read it through AccessContext.chat, and it can be referenced
/// only from EncryptedContent in that chat.
case chat(Flipcash_Common_V1_ChatId)

}
Expand Down
16 changes: 8 additions & 8 deletions Sources/Flipcash2ClientProtocol/blob_v1_model.pb.swift
Original file line number Diff line number Diff line change
Expand Up @@ -808,11 +808,11 @@ public struct Flipcash_Blob_V1_AccessContext: Sendable {

/// The caller is accessing these blobs from this user's public profile.
/// Authorized iff the blob is a rendition of that user's CURRENT profile
/// picture — a profile grants nothing else, and a superseded picture's
/// renditions stop resolving through it.
/// picture or cover picture — a profile grants nothing else, and a
/// superseded picture's renditions stop resolving through it.
///
/// A caller never needs this for its OWN profile picture, since it owns
/// those blobs.
/// A caller never needs this for its OWN pictures, since it owns those
/// blobs.
public var userProfile: Flipcash_Common_V1_UserId {
get {
if case .userProfile(let v)? = scope {return v}
Expand Down Expand Up @@ -844,11 +844,11 @@ public struct Flipcash_Blob_V1_AccessContext: Sendable {
case chat(Flipcash_Common_V1_ChatId)
/// The caller is accessing these blobs from this user's public profile.
/// Authorized iff the blob is a rendition of that user's CURRENT profile
/// picture — a profile grants nothing else, and a superseded picture's
/// renditions stop resolving through it.
/// picture or cover picture — a profile grants nothing else, and a
/// superseded picture's renditions stop resolving through it.
///
/// A caller never needs this for its OWN profile picture, since it owns
/// those blobs.
/// A caller never needs this for its OWN pictures, since it owns those
/// blobs.
case userProfile(Flipcash_Common_V1_UserId)
/// The caller is accessing these blobs from this chat's public profile.
/// Authorized iff the blob is a rendition of that chat's CURRENT profile
Expand Down
Loading
Loading