fix(mobile): configure iOS Keychain access group - #3665
Conversation
This keeps development iOS builds aligned with the bundle-scoped Keychain storage used by SecureStore during local simulator pairing.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Approved This is a standard iOS configuration change adding keychain-access-groups entitlement with the app's own bundle identifier. The change is declarative, follows standard patterns, and poses minimal risk. You can customize Macroscope's approvability policy. Learn more. |
|
Context for the human review flagged above: the declared group |
…in-access-group # Conflicts: # apps/mobile/app.config.ts
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit b6cb69b. Configure here.
|
Maintainer verification: the one-file entitlement change is the documented fix for the SecureStore access-group error and nothing else changes. Two things before merge: the base is ~2 months old and needs a rebase, and I noticed the group uses variant.iosBundleIdentifier rather than the resolved personal-team identifier — personal-team builds would get the non-personal group, though those builds already lose app-groups/push per the config comments. Please confirm production signing embeds the group per variant and re-validate pairing plus relaunch on a real device, not just the simulator. |
## What's Changed * fix(mobile): keep pending messages in the chat timeline by @juliusmarminge in pingdotgg/t3code#10449 * fix(mobile): show connection status in the floating pill instead of a second one by @juliusmarminge in pingdotgg/t3code#10440 * fix: use Pierre icons consistently for attachments by @juliusmarminge in pingdotgg/t3code#10475 * feat(mobile): open the thread screen as soon as a new task is submitted by @juliusmarminge in pingdotgg/t3code#10435 * fix(devcontainer): make repository setup work by @saphid in pingdotgg/t3code#7875 * fix(projects): prevent invalid script IDs from crashing threads by @saphid in pingdotgg/t3code#10019 * fix(mobile): hide changed-files navigator and restore refresh in raw diff fallback by @lnieuwenhuis in pingdotgg/t3code#9828 * fix(ios): scroll short source files from blank space by @juliusmarminge in pingdotgg/t3code#10178 * feat(mobile): start a new thread on an existing branch by @StiensWout in pingdotgg/t3code#10359 * fix(mobile): improve font-size slider performance and prevent maximum update depth errors by @bbernag in pingdotgg/t3code#7138 * fix(web): keep composer toolbar controls anchored during transitions by @juliusmarminge in pingdotgg/t3code#10478 * fix(web): resize the floating preview from any edge by @juliusmarminge in pingdotgg/t3code#10467 * fix(mobile): prevent chat from disappearing when scrolling by @juliusmarminge in pingdotgg/t3code#10479 * fix(mobile): smooth composer status pill resizing by @juliusmarminge in pingdotgg/t3code#10484 * fix(mobile): release initial scroll target after dragging by @juliusmarminge in pingdotgg/t3code#10483 * fix(mobile): animate thread lifecycle transitions consistently by @juliusmarminge in pingdotgg/t3code#10487 * fix(mobile): restore assistant message bottom padding by @juliusmarminge in pingdotgg/t3code#10491 * fix(mobile): preserve chat rows when toggling commands by @juliusmarminge in pingdotgg/t3code#10492 * feat(web): group onboarding project import by repository by @t3dotgg in pingdotgg/t3code#10493 * fix(web): remove inserted citations on cancel by @extoci in pingdotgg/t3code#10518 * fix(mobile): match Working status color to desktop by @baptisteArno in pingdotgg/t3code#10515 * fix(mobile): wait for native thread scroll before reveal by @juliusmarminge in pingdotgg/t3code#10486 * fix(web): tolerate servers that predate git identity in project import by @juliusmarminge in pingdotgg/t3code#10547 * fix(web): restore settled PR colors on hover by @flamboh in pingdotgg/t3code#10023 * fix(web): keep popup triggers steady when pressed by @dominic-r in pingdotgg/t3code#10468 * fix(web): keep project favicon shape consistent across sizes by @sameerr03 in pingdotgg/t3code#10502 * fix(claude): report usage limits on retried turns by @StiensWout in pingdotgg/t3code#10549 * refactor(desktop): classify backend exports by @juliusmarminge in pingdotgg/t3code#10265 * refactor(desktop): classify electron exports by @juliusmarminge in pingdotgg/t3code#10266 * refactor(desktop): classify app exports by @juliusmarminge in pingdotgg/t3code#10267 * refactor(desktop): classify preview exports by @juliusmarminge in pingdotgg/t3code#10268 * ci(knip): enforce desktop exports by @juliusmarminge in pingdotgg/t3code#10269 * fix(web): remove excess sidebar thread spacing by @maria-rcks in pingdotgg/t3code#10569 * fix(web): make settings project scopes searchable and scrollable by @maria-rcks in pingdotgg/t3code#10570 * fix(web): use `tabular-nums` with the ui font for sidebar timer by @extoci in pingdotgg/t3code#10592 * fix(web): correct pending question attachment message by @dominic-r in pingdotgg/t3code#10599 * fix(mobile): restore brand artwork in the Android adaptive icon by @juliusmarminge in pingdotgg/t3code#10598 * fix(mobile): configure iOS Keychain access group by @VedankPurohit in pingdotgg/t3code#3665 * fix(web): remember Composer Fast mode across new chats by @aravhawk in pingdotgg/t3code#2981 * fix(server): disable executable capabilities in Claude metadata generation by @maxwellyoung in pingdotgg/t3code#4169 * Add stop thread keybinding command by @jakeleventhal in pingdotgg/t3code#4308 ## New Contributors * @bbernag made their first contribution in pingdotgg/t3code#7138 * @baptisteArno made their first contribution in pingdotgg/t3code#10515 * @aravhawk made their first contribution in pingdotgg/t3code#2981 **Full Changelog**: pingdotgg/t3code@v0.0.39...v0.0.40 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.40
## What's Changed * fix(mobile): wait for native thread scroll before reveal by @juliusmarminge in pingdotgg/t3code#10486 * fix(web): tolerate servers that predate git identity in project import by @juliusmarminge in pingdotgg/t3code#10547 * fix(web): restore settled PR colors on hover by @flamboh in pingdotgg/t3code#10023 * fix(web): keep popup triggers steady when pressed by @dominic-r in pingdotgg/t3code#10468 * fix(web): keep project favicon shape consistent across sizes by @sameerr03 in pingdotgg/t3code#10502 * fix(claude): report usage limits on retried turns by @StiensWout in pingdotgg/t3code#10549 * refactor(desktop): classify backend exports by @juliusmarminge in pingdotgg/t3code#10265 * refactor(desktop): classify electron exports by @juliusmarminge in pingdotgg/t3code#10266 * refactor(desktop): classify app exports by @juliusmarminge in pingdotgg/t3code#10267 * refactor(desktop): classify preview exports by @juliusmarminge in pingdotgg/t3code#10268 * ci(knip): enforce desktop exports by @juliusmarminge in pingdotgg/t3code#10269 * fix(web): remove excess sidebar thread spacing by @maria-rcks in pingdotgg/t3code#10569 * fix(web): make settings project scopes searchable and scrollable by @maria-rcks in pingdotgg/t3code#10570 * fix(web): use `tabular-nums` with the ui font for sidebar timer by @extoci in pingdotgg/t3code#10592 * fix(web): correct pending question attachment message by @dominic-r in pingdotgg/t3code#10599 * fix(mobile): restore brand artwork in the Android adaptive icon by @juliusmarminge in pingdotgg/t3code#10598 * fix(mobile): configure iOS Keychain access group by @VedankPurohit in pingdotgg/t3code#3665 * fix(web): remember Composer Fast mode across new chats by @aravhawk in pingdotgg/t3code#2981 * fix(server): disable executable capabilities in Claude metadata generation by @maxwellyoung in pingdotgg/t3code#4169 * Add stop thread keybinding command by @jakeleventhal in pingdotgg/t3code#4308 ## New Contributors * @aravhawk made their first contribution in pingdotgg/t3code#2981 **Full Changelog**: pingdotgg/t3code@v0.0.40-nightly.20260907.1359...v0.0.40-nightly.20260907.1372 Upstream release: https://github.com/pingdotgg/t3code/releases/tag/v0.0.40-nightly.20260907.1372
Merges `pingdotgg/t3code` `8b2838e0e..a37c664` — 43 commits. `343` files landed against `343` changed in the upstream range; fork delta `723` files. Exact match, so nothing upstream changed was dropped. Details in [`docs/fork/upstream-merge-log.md`](../blob/merge/upstream-2026-09-08/docs/fork/upstream-merge-log.md). ## Two fork deltas this merge had to re-apply **Upstream split the server-update banner into two routes.** pingdotgg#10596 added `useAutoBalanceUpdateBanner` beside the single-machine condition the fork already gates. The conflict was on the first line only, so resolving it correctly still left the auto-balance route ungated — an auto-balanced project would have been offered `npx t3` against a backend that does not implement `server.updateServer`. `FEATURES.serverUpdateBanner` now carries two gates in `ChatView.tsx`. **A new settings page needs a gate even though it degrades politely.** pingdotgg#8103 added `/settings/snap-shot` for desktop window capture. Every control drives `window.desktopBridge`, and upstream renders an "unavailable" notice rather than hiding the page, so a hosted build listed a sidebar section and six searchable rows for a feature it can never run. Gated with `FEATURES.snapShots`. Two smaller fixes: `packages/moatless-api` still ran `tsgo --noEmit` after upstream replaced `@typescript/native-preview` with TypeScript 7.0.2, and `duplicate-adds.mjs` now skips `pnpm-lock.yaml` (it read `iconv-lite: 0.6.3` as taken twice; `d3-dsv` and `encoding` each declare it). ## Usable as-is - Stop-thread keybinding command (pingdotgg#4308). - Project import tolerates servers that predate the git-identity scan (pingdotgg#10547). - Proactive panels open when entering a thread (pingdotgg#10610); pull-request markdown links open in the panel (pingdotgg#10623); markdown images navigate as galleries (pingdotgg#10625); pull-request videos play inline (pingdotgg#10617). - Settings project scopes are searchable and scrollable (pingdotgg#10570); ref picker stays steady when opening (pingdotgg#9472); sidebar timer uses `tabular-nums` (pingdotgg#10592); popup triggers stay steady when pressed (pingdotgg#9468); settled PR colors restore on hover (pingdotgg#10023). - Composer Fast mode persists across new chats (pingdotgg#2981); inserted citations are removed on cancel (pingdotgg#10518). - TypeScript 7.0.2 (pingdotgg#10663) and the knip desktop-export rules (pingdotgg#10269). ## Unsupported in Moatless / needs implementation - **Cross-platform window capture** (pingdotgg#8103) — `apps/desktop/src/snapShot/**`, `apps/web/src/components/settings/SnapShotSettings.tsx`, `apps/web/src/lib/desktopSnapShot.ts`. Needs an Electron `window.desktopBridge`; a browser tab has none. Gated behind `FEATURES.snapShots` in this PR. - **Auto-balance server update** (pingdotgg#10596) — `apps/web/src/components/chat/useAutoBalanceUpdateBanner.tsx`. Needs `server.updateServer`, which Moatless does not dispatch. Gated behind `FEATURES.serverUpdateBanner` in this PR. - **Preview recording transfer** (pingdotgg#10572) — `apps/server/src/mcp/toolkits/preview/handlers.ts`, `apps/web/src/browser/browserRecordingUpload.ts`. Moves a finished preview recording into the agent environment over the desktop bridge. Adds four error types to `packages/contracts/src/previewAutomation.ts` and no new RPC method, so no union changed. Sits behind the `previewAutomation.connect` / `focusHost` / `respond` gap already in the register. - **Local media linked from remote threads** (pingdotgg#10619) and **browser editing shortcuts** (pingdotgg#10621) — Electron shell only. - **iOS Keychain access group** (pingdotgg#3665) and the mobile provider account badge (pingdotgg#9899) — the fork ships no mobile build against Moatless. ## Backend behavior to consider reproducing in Moatless - **Name the usage limit and its reset instead of relaying "out of credits"** (pingdotgg#10473, `apps/server/src/provider/**` Codex adapter). Moatless owns its provider runtime, so the clearer limit message has to be produced there. - **Report usage limits on retried turns** (pingdotgg#10549, Claude adapter). A retry currently loses the limit signal; same ownership. - **Disable executable capabilities in Claude metadata generation** (pingdotgg#4169, `apps/server/src/textGeneration/ClaudeTextGeneration.ts`). Title and metadata generation should not be able to run tools. Worth mirroring wherever Moatless generates thread titles. ## Verification `verify.mjs`: duplicate-adds, tripwires, resolution-check, unsupported-methods (0 ADD, 0 DROP, 2 KEEP), fmt, lint and typecheck all pass. Tests pass except `@t3tools/desktop`, which cannot compile `scripts/browser-secret-native.test.mjs` because the sandbox has no `libsecret-1` — 1283 tests pass, 0 fail, and the file is byte-identical to upstream. New entry in `docs/fork/gaps.md`. `t3` failed `GrokAdapter.test.ts` once under parallel load and passes 42/42 alone. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- Moatless task: https://moatless.soaplabstest.com/tasks/6d8ea486-2fcb-4c25-bd34-dcd15cc4a7ac

Summary
The mobile app stores connection credentials through
expo-secure-store, which uses the iOS Keychain. During iOS simulator pairing, SecureStore previously failed with:The Expo iOS config did not explicitly declare a bundle-scoped Keychain access group. This adds
$(AppIdentifierPrefix)<bundle identifier>for each app variant.Test plan
vp run --filter @t3tools/mobile test -- app.config.test.tsvp run typecheckvp run lint:mobilevp checkNotes
This app uses Expo native tooling/dev-client style builds, not Expo Go.
On this Xcode simulator setup, the installed simulator app still reports empty embedded entitlements because Xcode reports
ENTITLEMENTS_ALLOWED = NO. The runtime pairing and SecureStore read-back flow was validated successfully.Note
Low Risk
Narrow native signing/entitlement config change for Keychain; no new storage paths or auth logic.
Overview
Fixes iOS SecureStore failures during simulator pairing (
getValueWithKeyAsync/ missing entitlement) by declaring an explicitkeychain-access-groupsentitlement in Expo iOS config.Each app variant gets
$(AppIdentifierPrefix)<variant bundle id>so Keychain access matches the signed bundle; credential storage still goes throughexpo-secure-storeonly.Reviewed by Cursor Bugbot for commit 2853524. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Add keychain-access-groups entitlement to iOS builds
Adds
ios.entitlementsto app.config.ts with akeychain-access-groupsentry set to$(AppIdentifierPrefix)<bundleIdentifier>. This configures the app to participate in the correct iOS keychain access group at runtime.Macroscope summarized 2853524.