Repository navigation
fix(mobile): recover the provider review inbox when a connection needs reconnecting - #7895
Conversation
A provider connection failure (credential refused by the broker, a rejected token, an inactive integration, or a missing repository scope) was classified as the provider 'forbidden' kind and surfaced as FORBIDDEN, which the mobile PR review inbox renders as a permanent 'you don't have permission' state with no action. An organization member's Kilo access is not what failed, so the state lied about the cause. The provider read layers now carry a 'reconnect' kind: credential refusals, rejected tokens, inactive integrations, and the insufficient-permission repository cache all map to it, the router surfaces it as PRECONDITION_FAILED (the mobile reconnect state), and an inbox list read reclassifies a provider 403 as a connection failure because the inbox has no per-merge-request permission context. The merged inbox reports which provider produced the terminal state so the reconnect notice re-checks that provider and its organization scope instead of GitHub, which cannot fix an expired GitLab connection.
Code Review SummaryStatus: No Issues Found | Recommendation: Merge The branch's current diff against Assumptions: Files Reviewed (15 files)
Previous Review Summaries (3 snapshots, latest commit 1cc3061)Current summary above is authoritative. Previous snapshots are kept for context only. Previous review (commit 1cc3061)Status: No Issues Found | Recommendation: Merge Executive SummaryThe only change since the previous review is the main-branch consolidation of the GitLab/Bitbucket error classes onto the shared Files Reviewed (4 files)
Verification notes: Previous review (commit a713292)Status: No Issues Found | Recommendation: Merge Executive SummaryThe incremental change set is a behavior-preserving refactor: extracting the Files Reviewed (4 files)
Notes on what was checked: the new Previous review (commit b634dff)Status: No Issues Found | Recommendation: Merge Executive SummaryThe provider-connection failure reclassification ( Files Reviewed (17 files)
Notes on what was checked: the Reviewed by deepseek-flash-latest · Input: 140.5K · Output: 28.4K · Cached: 2.6M Review guidance: REVIEW.md from base branch |
Fold the reconnect-notice coverage into the existing mounted suites and merge duplicate merge tests so every touched mobile file stays under the 300-line cap. Also update the branch listing test to the reconnect classification: an inactive integration is PRECONDITION_FAILED, not a missing one.
|
bot: Follow-up session. The head commit keeps the branch green (lint, tests, typecheck all pass; the earlier lint/test failures were fixed by a713292). The PR body now lists all three proxy answers in the required question/answer format, and the placeholder screenshot link was replaced with two real Android emulator screenshots attached from this session's verification: the organization scope shows the GitLab reconnect notice with the Check connection action, and the Personal scope shows the normal empty state. No code changes were needed; the review loop is converged. |
…-org-member # Conflicts: # apps/web/src/lib/provider-review/gitlab-authorization.test.ts # apps/web/src/lib/provider-review/gitlab-authorization.ts # apps/web/src/lib/provider-review/gitlab-read.ts # apps/web/src/routers/provider-review-router.test.ts # apps/web/src/routers/provider-review-router.ts
…nect The owner-aware classifier rewrites an organization connection's 403 into a reconnect whose message names a merge request. The inbox list request never mentions one, so the classification now reads the provider status first and answers every 403 on that read with the inbox copy.
|
bot: Android emulator proof of the provider review inbox, on the local dev stack with the fixture organization and one local stub serving the provider APIs and token brokers.
Backend observed for the same run: the organization GitLab status is what "Check connection" re-checks for the member, and both inbox reads answer PRECONDITION_FAILED instead of FORBIDDEN. |
…-org-member # Conflicts: # apps/mobile/src/lib/pr-review/classify-pr-review-query-state.ts



Evidence
Evidence: demonstrated — an Android emulator run against the local dev stack, with the provider APIs and token brokers stubbed at the network boundary, showed the inbox reconnect notice where the permanent permission state had been, the Check-connection action re-checking the failing provider for that member, and the review list after the provider answered again.
Change
An organization member whose provider connection broke got a dead end in the provider review inbox: the read layer classified the failure as
forbidden, the router surfacedFORBIDDEN, and the inbox rendered its permanent "you don't have permission to view this content" state — no list, no retry, no way out. The member's Kilo access was never the problem; the provider connection was.Main now carries the GitLab half of that classification (an organization connection's 403 on a read resolves to
reconnect), so this branch keeps the parts that main does not have and merges cleanly onto it:401), an integration that reportsreconnect_required, a workspace whose repository scope is insufficient, and a provider 403 on the inbox collection all classify asreconnectinstead offorbidden/not_found. A genuine per-pull-request refusal keeps its permission semantics elsewhere.listInboxreads the provider status before the owner-aware classification and answers every 403 on that read withreconnectand inbox copy — the list request names no merge request, so the connection wording must not either.providerReviewmapsreconnecttoPRECONDITION_FAILED, and the branch listing maps both provider error types the same way.No copy or catalog changes: the reconnect notice already carried the GitLab and Bitbucket titles and the "Check connection" action.
End-to-end evidence (Android emulator on the work VM)
Local dev stack (postgres + nextjs + Metro) with a seeded fixture organization and a signed-in member. Both forge APIs and all three token brokers are served by one local stub at the network boundary, so the provider collection can be refused and then served in the same run. The member's GitLab and Bitbucket inbox collections were refused with
403first, then allowed.Observed on the emulator, organization scope:
PRECONDITION_FAILED.Backend observed for the same run:
organizations.reviewAgent.getGitLabStatusfor the member (no GitHub authorization check), andproviderReview.listInboxanswering412/PRECONDITION_FAILED— noFORBIDDENon the inbox read.Driver results against the real tRPC router (same stack, same stub):
Provider boundary: the run exercised
GET /api/v4/user,GET /api/v4/merge_requests?scope=reviews_for_me,GET /2.0/repositories/{workspace}andGET /2.0/repositories/{workspace}/{repo}/pullrequests, plus the GitLab and Bitbucket workspace token broker calls. Real provider accounts, review-job dispatch, webhooks and model calls were not exercised and stay source-inspected.Tests
bitbucket-authorization.test.ts/bitbucket-read.test.ts: broker refusal,401, Revoke-stylereconnect_required, insufficient repository scope and an inbox 403 all classify as reconnect; a missing integration stays not-found;listInboxreclassifies a provider 403.gitlab-read.test.ts:listInboxreclassifies a provider 403 as reconnect for a personal connection and keeps the inbox wording for an organization connection.gitlab-authorization.test.ts,provider-review-router.test.ts,cloud-agent-next-router.branches.test.ts: unchanged behaviour after the merge; the router maps reconnect toPRECONDITION_FAILEDand a real refusal toFORBIDDENon both the read and inbox paths.use-provider-inbox.test.ts: the merge names the provider of the terminal state, only when every enabled provider failed.pr-review-inbox-list.mounted.test.tsx: the reconnect state passes the failing platform and organization to the notice and renders no permission view.Verified on the work VM after the merge:
apps/webjest for the four provider-review suites (129 tests) and the two router suites (46 tests),apps/mobilevitest forsrc/lib/pr-review+src/components/pr-review(1438 tests),tsgo --noEmitforapps/web,tsc --noEmitforapps/mobile, oxlint on the changed files.Proxy answers
The owner's proxy gave these answers in the owner's place.
Answer: Reconnect on inbox 403 only
Confidence: 0.65 · Precedent: Fix the root cause and the class of the issue: session 7f3470e0ba6f, "fix class of issue preventing progress". An inbox list 403 has no PR context, and detail-screen permission semantics stay intact.
Answer: No, fix the classification
Confidence: 0.55 · Precedent: Do the least work possible with no drop in quality: session 7f3470e0ba6f, "do the least amount of work possible, with no drop in quality". It also avoids a broker round trip on a hot status path, per the performance-reviewer rule.
Answer: Yes, one reconnect meaning
Confidence: 0.80 · Precedent: Keep similar elements consistent across surfaces, and fix the class: session 00eb2a1d3e4b, "if anything repeats the same mistake over and over again, fix the class".
Screenshots are attached in a separate comment.