fix(mobile): bind Kilo Chat effects to local access - #5664
Conversation
| } catch { | ||
| toast.error(buildAttachmentUnreadableToast(attachment.filename)); | ||
| if (client.canStartOperation()) { | ||
| toast.error(buildAttachmentUnreadableToast(attachment.filename)); |
There was a problem hiding this comment.
WARNING: Stale admission denials are toasted as unreadable files after unlock
assertDispatch() failures in this loop are caught together with materialize errors. After lock/unlock, canStartOperation() succeeds, so a delayed multi-select continuation toasts buildAttachmentUnreadableToast instead of staying silent. Treat LocalAccessDeniedError (or getLocalAccessDenial) as a silent drop.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
| ); | ||
| if (client.canStartOperation()) { | ||
| toast.error( | ||
| error instanceof Error ? error.message : i18n.t('chat.attachment.attachFailed') |
There was a problem hiding this comment.
WARNING: Delayed picker admission failures surface internal error messages
A camera/library/file return hits addSelectedAttachments's assertDispatch(). After unlock, canStartOperation() is true, so LocalAccessDeniedError is toasted as error.message (Local access denied: stale) instead of a silent drop. Gate on the denial type, not whether a new operation can start.
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Code Review SummaryStatus: 2 Issues Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Files Reviewed (20 files)
Fix these issues in Kilo Cloud Reviewed by grok-4.6 · Input: 134.3K · Output: 27.3K · Cached: 1.3M Review guidance: REVIEW.md from base branch |
|
Retired. The owner cancelled this section and restarted the work with a tighter brief. The biometric gate scope grew into a full native-action admission audit; the replacement covers initial app unlock only. |
Summary
KiloChatOperationkeeps immutable dispatch admission through queues and unauthorized retries; owner-only publication lets already accepted work settle without renewed foreground access.KiloChatClientConfigadds optionalcaptureOperationAdmissionandcanPublishcallbacks, preserving existing callers; reads, typing cleanup, and status refresh require ownership only.KiloChatClient.captureOperationrejects foreign operations,canStartOperationgates announcements, anddisposeaborts requests, clears queues, and removes subscriptions.Files
packages/kilo-chat/src/client.ts— Source, modified, 280 lines changed; guards token waits, response decoding, events, and mutation dispatch while preserving per-conversation send order.packages/kilo-chat/src/types.ts— Source, modified, 12 lines changed; adds the readonly operation type and optional constructor callbacks.packages/kilo-chat/test/client.test.ts— Test, modified, 255 lines changed; extends the shared client tests.MobileKiloChatConfigmakes both guards mandatory increateMobileKiloChatClients, keeping connections, callbacks, and recovery tied to oneAuthenticatedOwner.KiloChatProviderremounts on ownership changes and replaces disposed clients during effect replay, rather than restoring old queues.KiloChatTokenErrorState.retrychecks admission at invocation; denial leaves the existing error and does not schedule that retry after access returns.Files
apps/mobile/src/components/kilo-chat/kilo-chat-provider.tsx— Source, modified, 267 lines changed; scopes clients and token identity by authentication epoch, generation, and user; guards subscriptions, reconnects, resyncs, activation, and teardown.apps/mobile/src/components/kilo-chat/kilo-chat-admission.test.ts— Test, added, 387 lines changed; adds mobile admission tests.apps/mobile/src/components/kilo-chat/kilo-chat-provider.mounted.test.tsx— Test, modified, 783 lines changed; extends the mounted provider tests.TokenCachenow includesAuthenticatedOwner;clearKiloChatTokenCacheinvalidates older pending fills, and cache reuse or request sharing requires matching credentials and ownership.TokenResponseListenerreceives the owner, whilekiloChat.getTokencarrieslocalAccessOwnerand rejects stale or mismatched user responses.TokenResponseGetteraccepts an optional dispatch check;useKiloChatTokenGetteranduseKiloChatTokenResponseGetteraccept optional owners and capture the current owner when omitted.Files
apps/mobile/src/components/kilo-chat/hooks/use-kilo-chat-token.ts— Source, modified, 143 lines changed; rechecks ownership around waits and listeners, matches authentication generations, and retains the early-expiry rule.apps/mobile/src/components/kilo-chat/hooks/use-kilo-chat-token.local-access.test.ts— Test, added, 134 lines changed; adds token access tests.useKiloChatMutationandKiloChatMutationOptionscapture variables, callbacks, and admission before React Query queues work, so rerenders cannot redirect settlement.mutateandmutateAsyncretain stable identities, accept an optional thirdKiloChatOperation, and preserve existing call forms and rejected variables.canPublishgates cache settlement, original admission gates per-call success/error callbacks, andonSettledcan release pending controls for the same locked owner.Files
packages/kilo-chat-hooks/src/use-messages.ts— Source, modified, 261 lines changed; guards sends, edits, deletions, reactions, redelivery, action execution, and message reads. It suppresses blocked notices and reuses the action-resolution helper.packages/kilo-chat-hooks/src/use-conversations.ts— Source, modified, 40 lines changed; guards creation, rename, leave, and mark-read; keeps reconciliation and suppresses blocked error notices.packages/kilo-chat-hooks/src/use-messages.test.ts— Test, modified, 270 lines changed; extends the message hook tests.packages/kilo-chat-hooks/src/use-conversations.test.ts— Test, modified, 144 lines changed; extends the conversation hook tests.PerformUpload,AddFileInput.operation, andUseAttachmentQueueOptions.captureOperationcarry captured admission from attachment selection through initialization and final upload dispatch, without renewing permission after waits.mobilePerformUploadrequires an operation; shared callers retain the optional form, and owner checks prevent stale progress, completion, or failure updates.UseAttachmentQueueResult.retryFileaccepts an optional operation; explicit retries validate supplied admission or capture a new operation while retaining local bytes.Files
packages/kilo-chat-hooks/src/use-attachment-queue.ts— Source, modified, 203 lines changed; pins upload ownership and validates initialization, final dispatch, and retries with cached upload links. It guards progress and settlement while retaining local bytes.apps/mobile/src/components/kilo-chat/message-input-attachment-queue.tsx— Source, modified, 86 lines changed; captures admission before camera, library, file, or clipboard preparation; carries it through selection and gates attachment error notices.apps/mobile/src/components/kilo-chat/mobile-perform-upload.ts— Source, modified, 15 lines changed; rejects missing admission before calling the shared uploader.packages/kilo-chat-hooks/src/use-attachment-queue.test.ts— Test, modified, 188 lines changed; extends the attachment queue tests.packages/kilo-chat-hooks/src/xhr-perform-upload.test.ts— Test, modified, 29 lines changed; extends the shared upload adapter tests.packages/kilo-chat/test/client.attachments.test.ts— Test, modified, 47 lines changed; extends the attachment request tests.useConversationMarkReadkeeps each scheduled attempt's originalKiloChatOperationand callback, cancelling retries when access, ownership, focus, or the message marker changes.useMarkReadadds an optional operation argument;MarkReadInputpreserves that operation, the user, and the inner mutation before the outer queue waits.Badge updates, native counts, diagnostics, and invalidation require the original owner; accepted responses can settle without foreground access, with existing freshness checks intact.
Files
apps/mobile/src/components/kilo-chat/hooks/use-conversation-mark-read.ts— Source, modified, 113 lines changed; retains the scheduled retry closure and admission; cancels invalid timers and removes listeners on unmount.apps/mobile/src/components/kilo-chat/hooks/use-mark-read.ts— Source, modified, 96 lines changed; captures the user and inner mutation before queuing; guards badge effects, diagnostics, invalidation, and returned results.Tests: 9 files: 2 added, 7 modified; 2,237 changed lines across
client.test.ts,kilo-chat-admission.test.ts,kilo-chat-provider.mounted.test.tsx,use-kilo-chat-token.local-access.test.ts,use-messages.test.ts,use-conversations.test.ts,use-attachment-queue.test.ts,xhr-perform-upload.test.ts, andclient.attachments.test.ts.Generated: 0 files.
Visual Changes
Visual Changes: N/A
Verification
Reviewer Notes
mobile-context-lock-758a-s3tomobile-context-lock-758a-s4.Kilo-Org/cloud; worktree:/Users/igor/Projects/.worktrees/mobile-context-lock-758a.Human steps
pnpm install --filter kilo-app...from the repository root.rm -rf "$TMPDIR/metro-cache" "$TMPDIR"/metro-file-map-*.Notes
This level adds Kilo Chat admission and ownership boundaries without exposing biometric controls. Full iOS and Android verification runs on the final stack level.
Runtime verification remains bot-e2e, not human delegation.
Stacked PRs — merge bottom to top. Each level shows only its own diff.
Runtime verification (E2E, user advocacy, simplify) runs on the tip PR over every level.
Every level keeps its own checks, its own bot review, and its own threads; each one is answered on its own PR.
Each level is its own deliverable: it builds and passes its own checks alone.
A finding on a level is repaired on that level, then carried upward with stack.sh forward.
mobile-context-lock-758a— feat(mobile): add account-owned local access state #5642mobile-context-lock-758a-s2— fix(mobile): bind restored context and drafts to account scope #5651mobile-context-lock-758a-s3— fix(mobile): enforce local access at final transport dispatch #5658mobile-context-lock-758a-s4— fix(mobile): bind Kilo Chat effects to local access #5664 ← this PRmobile-context-lock-758a-s5— feat(mobile): protect native privacy and accessibility boundaries #5683 (tip)