Skip to content

feat(chat): require an idempotency key on StartChat - #787

Merged
bmc08gt merged 2 commits into
mainfrom
feat/chat-start-idempotency-key
Sep 16, 2026
Merged

bmc08gt merged 2 commits into
mainfrom
feat/chat-start-idempotency-key

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

Draft: blocked on code-payments/flipcash2-client-protocol#14. This branch pins flipcash2-client-protocol 0.8.0, and no such tag exists yet, so the exact: requirement has nothing for SPM to resolve. It goes green once that PR merges and publishes.

What changed upstream

StartChatRequest gained a required idempotency_key (field 9), backed by a new 16-byte IdempotencyKey message. Nothing was removed and nothing was renumbered — StartChatResponse.Result keeps all six cases in order, so ErrorStartChat's positional rawValue mapping is unaffected. Confirmed by reading the mapping, not assumed.

What this does

idempotencyKey: UUID becomes a required parameter — no default — on both layers that exist: ChatService.startChat and the FlipClient.startChat wrapper that threads it through.

UUID rather than raw Data because the existing UUID.data extension is exactly the 16 bytes the proto's min_len: 16 / max_len: 16 demands, and because it matches the precedent already in this codebase: sendMessage's clientMessageID: UUID, which ConversationController.send/.retry mint once and reuse across retries of the same logical send.

No default value is the point of the change. The server derives the chat's identity from caller plus key, so a key minted inside the call, fresh per attempt, would pass validation while producing exactly the duplicate chats the field prevents. Forcing the caller to supply it keeps minting where the user's intent originates. Both doc comments say so.

Ordering is preserved: $0.auth = owner.authFor(message: $0) still runs last, so the signature covers the new field.

Scope left open

There is no group-chat-creation screen on main — startChat has no caller above FlipClient, so there is no retry path yet in which to reuse a key. (Every other startChat* match in the tree is the unrelated startChatting tip-DM fee concept.) A ConversationController-level create/retry pair analogous to send/retry is the natural home for that reuse, and belongs with the screen that needs it rather than here.

Builds

xcodebuild build -scheme Flipcash -destination generic/platform=iOS via Scripts/build.sh, against the client repo through FLIPCASH_PROTO_LOCAL / FLIPCASH_PROTO_LOCAL_PACKAGES=flipcash2 rather than a published tag — succeeds.

Package.resolved is unchanged: the local override drops the overridden package's entry while it is on, and that was restored before committing.

flipcash2 0.8.0 adds a required idempotency_key field to StartChatRequest:
a retry with the same key returns the original chat (result OK) instead of
creating a duplicate, even if the group title/picture/rules differ on the
retry.

Thread a UUID through ChatService.startChat and FlipClient.startChat as a
required parameter, encoded the same way clientMessageID already is for
SendMessage. The caller must mint the key once, where the user's intent to
create the chat originates, and reuse it across retries of that attempt.
There is no call site yet to wire that reuse into, so this scaffolds the
plumbing without inventing one.

Built against the local flipcash2-client-protocol override
(FLIPCASH_PROTO_LOCAL); no published release exists at this contract
version yet.
StartChat needs the idempotency_key field that 0.8.0 adds. Blocked until that
tag exists for SPM to resolve.
@bmc08gt bmc08gt self-assigned this Sep 16, 2026
@bmc08gt
bmc08gt marked this pull request as ready for review September 16, 2026 19:08
@bmc08gt
bmc08gt merged commit 883b83a into main Sep 16, 2026
1 of 2 checks passed
@bmc08gt
bmc08gt deleted the feat/chat-start-idempotency-key branch September 16, 2026 19:39
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