In channels members are usually connected via relays, so they are memberCurrent
but not memberActive, and #7255 widened the condition for requesting the member
security code to cover them. It updated GroupChatInfoView and
MemberSupportChatView, but not the same code in ChatView, so "Verify security
code" is not offered when the profile is opened by tapping member avatar in the
chat, while it is offered for the same member in the members list.
- core: reject service payloads nested deeper than 32 levels, so a hostile service cannot crash the app's JSON decoder
- core: one parseServiceBody (decompress, decode, depth check) at all three decode points: incoming requests, sendServiceRequestTo, redeemBadgeCode
- directory: '%' and '_' in search text match literally instead of acting as LIKE wildcards
- directory: search text over 100 characters is rejected over RPC
- directory: a new directory creates its address with DR keys, so service requests work without a manual key rotation
- directory: service requests are always processed; the --service-requests switch is no longer needed for the directory
- directory: the in-flight service request cap is a DirectoryOpts field (default 8) instead of a hardcoded constant
- directory: the page-fit check compresses the exact response object that is sent, not a proxy with a different key order and cursor
- directory: search entries omit the full link when a short link exists, saving hundreds of bytes per entry in the envelope
- ios: add DirectorySearch.swift and DirectorySearchView.swift to the Xcode project; the app did not build without them
- ios: in the onboarding state the search bar is at the bottom in one-hand mode, as in the chat list
- ios: in the onboarding state a failed search shows the retry row instead of returning to the cards
- ios: a search with no results shows a "No results" row
- ios: the "No chats found" overlay no longer covers directory results, the retry row or the no-results row
- ios: directory rows are rendered by one builder for both the onboarding and chat-list branches
- ios: retrying after a failed "Show more" resumes from the cursor instead of restarting the search
- ios: cancelling the spinner, or tapping a result mid-search, drops the pending request without clearing results already shown
- ios: typing during a search stops the spinner, and a stale response no longer clears a newer search's spinner
- ios: repeated Search taps for the same text while a search is in flight are ignored
- ios: channel results show the subscriber count and channel icon; group results show the group icon
- ios: remove the unused searchText parameter of SearchInDirectoryRow
- android: a directory search timeout no longer pops the retry alert (the UI will show a retry row)
- tests: RPC paging by the echoed cursor, literal wildcards and the length bound, rejection over the cap, page fitting to the envelope, nested payload rejection
- redeem errors are typed (CEBadgeRedeemError) instead of matched by text in the apps
- service timeout (A_SERVICE) decodes in the apps and offers Retry via the existing retry alert
- unexpected redeem errors show the error itself instead of a generic message
- service error codes are a typed enum in the apps (BadgeServiceErrorCode)
- CRBadgeRedeemed returns badge state, so the apps skip a second round-trip after redeem
- setBadgeAlertAcked is scoped to user_id
- badgeChanged updates non-active profiles, so other profiles' badges don't go stale
- pitch banner is not shown to a profile that already has a badge
- one badgeTypeName per platform, used by the badge screen and the badge info alert
- BadgeAlertKind and BadgeAlertPrice decode via standard JSON, no custom decoders
- dead "Support ended" title branch removed from Your Badge view
- kotlin: users from badge responses carry remoteHostId
- kotlin: redeem code field keeps the IME's cursor and composition state
- kotlin: "Get your code" shown in all flavours
- kotlin: "Don't show again" -> "Dismiss", matching iOS
- kotlin: parseBadgeCode moved next to its FFI in platform/Core.kt
- kotlin: BadgesView no longer cross-fades on badge state updates
- kotlin: section title not uppercased
- ios: redeem code field parses once per change
- ios: A_SERVICE rejected reason is not decoded
- CLI: "cannot redeem badge code: ..." with the source of the error
- comments clarified