Skip to content

feat(chat): scaffold roster summary, participation rules, and chat-profile blobs - #1464

Merged
bmc08gt merged 3 commits into
code/cashfrom
chore/flipcash2-roster-rules-sync
Sep 15, 2026
Merged

bmc08gt merged 3 commits into
code/cashfrom
chore/flipcash2-roster-rules-sync

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Sep 14, 2026

Copy link
Copy Markdown
Collaborator

Blocked on code-payments/flipcash2-client-protocol#12. Draft until 0.6.0 is published, because this pins a version that does not exist yet — Gradle resolution reports com.flipcash:flipcash2-client-protocol:0.6.0 FAILED until then. CI never sees the local override, since protoLocalRoot lives in untracked local.properties.

Why

flipcash2-protobuf-api renamed three fields in place and added group-chat metadata across #93#98. Nothing was renumbered, so the wire format is unchanged, but two of the renames are on fields this app reads and the third is on a oneof it builds, so the module does not compile against the new package without moving.

What changed

All under services/flipcash/src/main/kotlin/com/flipcash/services/:

File Change
internal/network/extensions/ProtobufToLocal.kt getSequence()getVersion() on EmojiReaction and ReactionUpdate; toChatMetadata() populates the three new fields; new toRosterSummary(), toChatRules(), toRuleRequirement() mappers
internal/domain/ChatMetadataMapper.kt the parallel DI-mapper path, kept identical to the extension path
internal/network/api/BlobStorageApi.kt .setProfile(.setUserProfile(, plus the new ChatProfile arm
models/chat/BlobAccessContext.kt new ChatProfile(chatId) variant
models/chat/ChatMetadata.kt picture, rosterSummary, rules, all trailing with defaults
models/chat/RosterSummary.kt, models/chat/ChatRules.kt new domain types
network/api/BlobAccessContextValidationTest.kt fixed the renamed call, added a chat-profile scope case

The proto rename is absorbed at the accessor: the domain field stays sequence, so the reaction ordering code above the mapper is untouched. Renaming it through the domain layer is a larger, separate change.

Worth a reviewer's attention

ListenerRules and SpeakerRules are separate proto messages with identical kind oneofs. This collapses them into one ChatRuleRequirement sealed interface, with ChatRules holding two lists of it, rather than mirroring the proto's two parallel types — the distinction the proto encodes is which list a requirement sits in, and that survives. iOS made the opposite call and kept two parallel enums (code-payments/code-ios-app#769), so the two platforms read differently here. Worth settling before anything consumes it.

An entry whose kind oneof is unset is dropped rather than defaulted, so a rule this client does not understand denies nothing instead of silently becoming a requirement it can evaluate.

Nothing in the app reads picture, rosterSummary, rules, or builds a ChatProfile access context yet. This is scaffolding to keep the module compiling against the new contract, not a behaviour change.

…ofile blobs

flipcash2-client-protocol synced to 35f99814 (six commits, #93-#98). Two of
its changes are wire-compatible renames that still break the build:
EmojiReaction and ReactionUpdate's `sequence` field became `version`, and
blob.v1.AccessContext's `profile` oneof arm became `user_profile` — an
exhaustive `when` over that oneof stops compiling on the rename alone,
before it even reaches the new `chat_profile` arm the same sync adds.

The rest is additive. chat.v1.Metadata gains `picture` (a group chat's
profile picture), `roster_summary` (member count plus a staleness version,
so a client can tell its cached roster went stale without holding the
roster itself), and `rules` (participation gates on listening and
speaking). Both proto-to-domain mapping paths — ProtobufToLocal's
toChatMetadata() and ChatMetadataMapper, which exist in parallel for
historical reasons — now populate all three the same way.

ListenerRules and SpeakerRules are two proto messages with an identical
`kind` oneof (minimum balance or staff), so they collapse into one domain
type, ChatRuleRequirement, used by both ChatRules.listener and
ChatRules.speaker. A `kind`-unset entry is dropped rather than defaulted:
inventing a requirement the server never sent would wrongly gate the chat,
and inventing "no requirement" would wrongly open it.

Nothing in the app reads picture, rosterSummary, or rules yet, so this is
scaffolding, not a feature: the new ChatMetadata fields default to
null/zero so the existing test constructors keep compiling, and no screen
shows a roster count or a rules gate. That UI work is a separate, open
product decision. BlobAccessContext.ChatProfile is wired the same way —
mapped to and from the proto, validated, and otherwise unconsumed.
0.6.0 is unpublished until flipcash2-client-protocol's sync PR merges and
publish.yml runs, so Gradle resolution fails here until then. The scaffold
commit ahead of this builds against the local checkout through
protoLocalRoot, which CI never sees.
@github-actions github-actions Bot added type: feature New functionality area: network gRPC, connectivity, API, exchange rates area: build-system Gradle, convention plugins, build-logic and removed type: feature New functionality labels Sep 15, 2026
@bmc08gt
bmc08gt merged commit 9d2f626 into code/cash Sep 15, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: build-system Gradle, convention plugins, build-logic area: network gRPC, connectivity, API, exchange rates

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant