Skip to content

Read linked pull requests in the desktop workspace - #812

Merged
alexeyzimarev merged 9 commits into
mainfrom
feat/desktop-pr-sidebar
Sep 8, 2026
Merged

alexeyzimarev merged 9 commits into
mainfrom
feat/desktop-pr-sidebar

Conversation

@alexeyzimarev

@alexeyzimarev alexeyzimarev commented Sep 8, 2026 •

Copy link
Copy Markdown
Member

Closes #811 — AI-2567

What & why

Read linked pull requests in a compact sidebar card and a native workspace tab, including checks, reviews, threads and conversation. Chat drafts and terminal hosts survive tab switches. Explicit selections stay unavailable when unlinked; GitHub links are bound to the selected PR. Reads use tenant authentication, access expiry and foreground masking.

Where to look

Deploy the compatible server (kurrent-io/kcap-server#1839) before releasing the desktop reader; charts: kurrent-io/kcap-deployments#614. Older servers retain safe external links. The shared HTTP factory disables redirects for authenticated PR reads.

Verification

dotnet suites: desktop 1,548 passed; PR wire/client 13 passed; HTTP container 43 passed; Linux daemon 3,048 passed, 27 skipped. Regression probes reproduce and fix shared-temp deletion and early permission settlement. Release CLI NativeAOT publish succeeded without warnings. The literal wire fixture is pinned to LF for Windows. Native views inspected with synthetic data. Paired deployed smoke test remains pending.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-08T07:54:09.963266Z 69f3dc2 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Add linked pull request reader to desktop workspaces

✨ Enhancement 🧪 Tests 📝 Documentation 🕐 40+ Minutes

Grey Divider

AI Description

• Adds sidebar PR summaries and a native reader for checks, reviews, threads, and conversation.
• Negotiates versioned tenant reads with bounded leases, masking, pagination, and safe links.
• Preserves chat and terminal state while adding protocol, lifecycle, and UI coverage.
Diagram

sequenceDiagram
    actor User as Desktop User
    participant UI as Workspace UI
    participant VM as PR View Model
    participant Source as Server Source
    participant Client as PR Client
    participant API as Tenant API
    participant GitHub
    User->>UI: Open PR reader
    UI->>VM: Select PR section
    VM->>Source: Request overview or page
    Source->>Client: Borrow authenticated channel
    Client->>API: GET versioned read
    API->>GitHub: Authorize and fetch
    GitHub-->>API: PR data
    API-->>Client: Envelope and access lease
    Client-->>VM: Validated typed result
    VM-->>UI: Render, retain, or mask
    UI-->>User: Native read-only view
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Embedded GitHub web view
  • ➕ Reuses GitHub's complete presentation and interaction model
  • ➕ Avoids maintaining native projections for every PR section
  • ➖ Introduces browser authentication, navigation, and content-isolation risks
  • ➖ Cannot provide the same bounded access masking and native state integration
  • ➖ Exposes write actions beyond the intended read-only scope
2. Local GitHub CLI or user tokens
  • ➕ Performs reads directly under the user's GitHub authorization
  • ➕ Could more closely match GitHub user-session permissions
  • ➖ Adds a local dependency or desktop credential lifecycle
  • ➖ Does not work consistently for remote daemons and ended sessions
  • ➖ Requires secure token storage, refresh, revocation, and cache partitioning
3. Proxy-hosted PR gateway
  • ➕ Keeps installation tokens and GitHub traffic entirely inside the shared proxy
  • ➕ Centralizes provider throttling and credential management
  • ➖ Adds a second PR read contract between proxy and tenant
  • ➖ Routes private PR bodies through an additional shared service
  • ➖ Moves session-specific admission and caching away from the tenant

Recommendation: Keep the PR's native, read-only reader backed by session-scoped tenant routes. It best preserves workspace state and remote-session support while keeping GitHub credentials out of the desktop; protocol negotiation, short access leases, foreground masking, and explicit safe links address the main security risks. A proxy gateway is reasonable only if token isolation becomes more important than minimizing service boundaries.

Files changed (67) +5055 / -238

Enhancement (48) +1610 / -61
App.axaml.csWire PR services into desktop workspaces +6/-2

Wire PR services into desktop workspaces

• Creates the server PR source, includes it in shared server-client cleanup, injects it into workspaces, and adds the existing GitHub-link browser action.

src/Capacitor.App/App.axaml.cs

ServerClients.csManage PR source authentication and cleanup +11/-3

Manage PR source authentication and cleanup

• Adds the pull-request source to cleanup and invalidates both work-context and PR authenticated leases after sign-in completes.

src/Capacitor.App/Services/ServerClients.cs

ServerPullRequestSource.csAdd the tenant-backed pull request source +50/-0

Add the tenant-backed pull request source

• Wraps the core PR client in redirect-safe authenticated reads. It also bounds consecutive missing-route recovery per session and supports explicit authentication resets.

src/Capacitor.App/Services/ServerPullRequestSource.cs

PullRequestChoice.csModel selectable linked pull requests +9/-0

Model selectable linked pull requests

• Adds a display choice that derives the canonical PR subject and repository-number label from link metadata.

src/Capacitor.App/ViewModels/PullRequestChoice.cs

PullRequestContextViewModel.Projections.csProject PR state into reader-friendly labels +128/-0

Project PR state into reader-friendly labels

• Maps overview and section data into lifecycle, checks, reviews, rows, snapshots, notices, and safe display states. Unknown and incomplete results remain explicitly qualified.

src/Capacitor.App/ViewModels/PullRequestContextViewModel.Projections.cs

PullRequestContextViewModel.Reads.csCoordinate PR discovery, polling, and pagination +177/-0

Coordinate PR discovery, polling, and pagination

• Implements capability-aware link discovery, overview renewal, on-demand section paging, restart handling, transient grace, and bounded page retention.

src/Capacitor.App/ViewModels/PullRequestContextViewModel.Reads.cs

PullRequestContextViewModel.csOwn desktop PR reader lifecycle and access state +272/-0

Own desktop PR reader lifecycle and access state

• Adds workspace-scoped PR selection, commands, cancellation generations, polling, foreground masking, access expiry, temporary display grace, and teardown.

src/Capacitor.App/ViewModels/PullRequestContextViewModel.cs

PullRequestRow.csDefine native PR reader rows +11/-0

Define native PR reader rows

• Adds a common row projection for checks, reviewers, reviews, threads, and comments, including availability, truncation, links, and memory sizing.

src/Capacitor.App/ViewModels/PullRequestRow.cs

PullRequestSectionState.csTrack bounded PR section snapshots +26/-0

Track bounded PR section snapshots

• Stores section pages, cursors, coverage, counts, errors, evicted handles, and estimated memory usage.

src/Capacitor.App/ViewModels/PullRequestSectionState.cs

WorkContextViewModel.Projections.csExpose the unique primary repository +2/-0

Expose the unique primary repository

• Derives the primary repository hash from session summary data so PR selection can prefer a matching branch and repository.

src/Capacitor.App/ViewModels/WorkContextViewModel.Projections.cs

WorkContextViewModel.csHost shared PR context in the sidebar model +5/-0

Host shared PR context in the sidebar model

• Adds the child PR view model, controls legacy-link visibility, and resets primary-repository hints when sessions change.

src/Capacitor.App/ViewModels/WorkContextViewModel.cs

WorkspaceViewModel.csAdd a persistent Pull Request workspace tab +25/-26

Add a persistent Pull Request workspace tab

• Makes the workspace own the PR view model and tab alongside Chat and Terminal. It preserves existing hosts, handles reconnects and no-terminal banners, and tears PR state down once.

src/Capacitor.App/ViewModels/WorkspaceViewModel.cs

MainWindow.axaml.csGate PR reads on active foreground workspaces +12/-2

Gate PR reads on active foreground workspaces

• Tracks the visible workspace and updates PR foreground eligibility from window visibility, activation, minimization, and navigation state.

src/Capacitor.App/Views/MainWindow.axaml.cs

PullRequestCard.axamlAdd the compact sidebar PR card +44/-0

Add the compact sidebar PR card

• Introduces linked-PR selection, summary status, refresh, native-reader navigation, safe external opening, sign-in, and GitHub-link actions.

src/Capacitor.App/Views/PullRequestCard.axaml

PullRequestCard.axaml.csInitialize the PR sidebar control +7/-0

Initialize the PR sidebar control

• Adds the code-behind entry point for the new Avalonia PullRequestCard.

src/Capacitor.App/Views/PullRequestCard.axaml.cs

PullRequestReader.axamlAdd the native pull request reader +80/-0

Add the native pull request reader

• Builds read-only description, checks, reviewers, reviews, threads, replies, and conversation views with paging, Markdown, snapshot labels, and explicit external actions.

src/Capacitor.App/Views/PullRequestReader.axaml

PullRequestReader.axaml.csPersist native reader scroll state +35/-0

Persist native reader scroll state

• Synchronizes reader scroll offsets with the selected PR and section, restoring positions after rows or sections change.

src/Capacitor.App/Views/PullRequestReader.axaml.cs

WorkContextView.axamlPlace the PR card in work context +4/-1

Place the PR card in work context

• Hosts the new shared PR card and hides duplicate legacy link cards when native PR context is available.

src/Capacitor.App/Views/WorkContextView.axaml

WorkspaceView.axamlExpose the Pull Request tab and host +8/-11

Expose the Pull Request tab and host

• Adds tab navigation and a dedicated reader host while preventing terminal banners from overlaying PR content.

src/Capacitor.App/Views/WorkspaceView.axaml

WorkspaceView.axaml.csLazily create and retain the PR reader +12/-16

Lazily create and retain the PR reader

• Creates the native reader on first activation, reuses it across tab switches, and preserves existing Chat and Terminal controls and focus behavior.

src/Capacitor.App/Views/WorkspaceView.axaml.cs

AuthModels.csAdvertise supported PR read protocol versions +3/-0

Advertise supported PR read protocol versions

• Adds the optional pull_request_reads_versions field to tenant authentication discovery responses.

src/Capacitor.Cli.Core/Auth/AuthModels.cs

CapacitorHttpClient.csAdd a redirect-safe protected read lane +3/-0

Add a redirect-safe protected read lane

• Provides authenticated, 401-recovering HTTP clients through the existing no-redirect memory lane for protected content reads.

src/Capacitor.Cli.Core/Http/CapacitorHttpClient.cs

ICapacitorHttpClient.csExpose protected authenticated reads +4/-0

Expose protected authenticated reads

• Adds the ForProtectedReadAsync contract for authenticated requests that must refuse redirects.

src/Capacitor.Cli.Core/Http/ICapacitorHttpClient.cs

IPullRequestSource.csDefine the pull request read source contract +11/-0

Define the pull request read source contract

• Introduces discovery, session reset, link-list, legacy-link, overview, and typed section-page operations.

src/Capacitor.Cli.Core/PullRequests/IPullRequestSource.cs

PullRequestActorDto.csModel PR users and teams +14/-0

Model PR users and teams

• Adds the wire representation for stable actor identity, kind, login, and display name.

src/Capacitor.Cli.Core/PullRequests/PullRequestActorDto.cs

PullRequestAvailabilityDto.csModel section availability +12/-0

Model section availability

• Adds status, reason, and fetch-time fields for independently available PR sections.

src/Capacitor.Cli.Core/PullRequests/PullRequestAvailabilityDto.cs

PullRequestCapability.csRepresent PR protocol discovery outcomes +5/-0

Represent PR protocol discovery outcomes

• Defines supported, legacy, unsupported, unavailable, signed-out, and invalid discovery states with version and retry metadata.

src/Capacitor.Cli.Core/PullRequests/PullRequestCapability.cs

PullRequestCheckDto.csModel check runs and commit statuses +36/-0

Model check runs and commit statuses

• Adds normalized check identity, source, outcome, provider, timing, URL, and head commit fields.

src/Capacitor.Cli.Core/PullRequests/PullRequestCheckDto.cs

PullRequestChecksSummaryDto.csModel overview check summaries +14/-0

Model overview check summaries

• Adds section availability, advisory rollup, head identity, and qualified outcome counts.

src/Capacitor.Cli.Core/PullRequests/PullRequestChecksSummaryDto.cs

PullRequestClient.csImplement the versioned tenant PR client +174/-0

Implement the versioned tenant PR client

• Negotiates server capabilities, performs bounded same-origin reads, validates typed envelopes and pagination invariants, applies discovery backoff, and supports independently admitted legacy links.

src/Capacitor.Cli.Core/PullRequests/PullRequestClient.cs

PullRequestCommentDto.csModel PR comments and replies +28/-0

Model PR comments and replies

• Adds published comment identity, author, Markdown body, truncation, timestamps, reply linkage, and availability.

src/Capacitor.Cli.Core/PullRequests/PullRequestCommentDto.cs

PullRequestContract.csPin the PR v1 fixture contract +5/-0

Pin the PR v1 fixture contract

• Records the canonical SHA-256 digest shared with the compatible tenant server implementation.

src/Capacitor.Cli.Core/PullRequests/PullRequestContract.cs

PullRequestConversationSummaryDto.csModel conversation summary state +10/-0

Model conversation summary state

• Adds conversation availability and its exact, lower-bound, or unknown comment count.

src/Capacitor.Cli.Core/PullRequests/PullRequestConversationSummaryDto.cs

PullRequestCountDto.csRepresent qualified PR counts +10/-0

Represent qualified PR counts

• Adds nullable count values with explicit exact, lower-bound, or unknown semantics.

src/Capacitor.Cli.Core/PullRequests/PullRequestCountDto.cs

PullRequestEnvelopeDto.csDefine common PR response envelopes +25/-0

Define common PR response envelopes

• Adds status, subject, data, timestamps, retry advice, polling cadence, access lifetime, and access-failure fields.

src/Capacitor.Cli.Core/PullRequests/PullRequestEnvelopeDto.cs

PullRequestErrorDto.csModel PR restart errors +10/-0

Model PR restart errors

• Adds the structured error and reason shape used for cursor and snapshot restart responses.

src/Capacitor.Cli.Core/PullRequests/PullRequestErrorDto.cs

PullRequestJsonContext.csGenerate NativeAOT-safe PR JSON metadata +16/-0

Generate NativeAOT-safe PR JSON metadata

• Registers all supported envelope and page specializations with System.Text.Json source generation.

src/Capacitor.Cli.Core/PullRequests/PullRequestJsonContext.cs

PullRequestLinkDto.csModel linked pull request identity +24/-0

Model linked pull request identity

• Adds provider, host, base repository, PR number, URL, title, and head branch metadata.

src/Capacitor.Cli.Core/PullRequests/PullRequestLinkDto.cs

PullRequestLinkListDto.csModel authoritative PR link lists +8/-0

Model authoritative PR link lists

• Adds the typed item collection returned by session-scoped link discovery.

src/Capacitor.Cli.Core/PullRequests/PullRequestLinkListDto.cs

PullRequestOverviewDto.csModel pull request overview content +36/-0

Model pull request overview content

• Adds lifecycle, branches, head SHA, description, review decision, access provenance, and section summaries.

src/Capacitor.Cli.Core/PullRequests/PullRequestOverviewDto.cs

PullRequestPageDto.csModel frozen PR collection pages +30/-0

Model frozen PR collection pages

• Adds snapshot identity and timing, coverage, qualified counts, page handles, continuation state, and typed items.

src/Capacitor.Cli.Core/PullRequests/PullRequestPageDto.cs

PullRequestRead.csRepresent normalized PR read outcomes +11/-0

Represent normalized PR read outcomes

• Defines ready, stale, unavailable, restart, sign-out, transport, and protocol outcomes. Access expiry is measured from request start to prevent network latency extending leases.

src/Capacitor.Cli.Core/PullRequests/PullRequestRead.cs

PullRequestReviewDto.csModel published PR reviews +28/-0

Model published PR reviews

• Adds review identity, state, author, Markdown body, truncation, timestamps, URL, and availability.

src/Capacitor.Cli.Core/PullRequests/PullRequestReviewDto.cs

PullRequestReviewerDto.csModel requested and current reviewers +22/-0

Model requested and current reviewers

• Adds user or team actor state, request status, latest review state, submission time, and availability.

src/Capacitor.Cli.Core/PullRequests/PullRequestReviewerDto.cs

PullRequestReviewsSummaryDto.csModel overview review counts +18/-0

Model overview review counts

• Adds availability and qualified counts for published reviews, approvals, requested changes, and outstanding users or teams.

src/Capacitor.Cli.Core/PullRequests/PullRequestReviewsSummaryDto.cs

PullRequestSubjectDto.csDefine canonical PR subjects +18/-0

Define canonical PR subjects

• Adds provider, host, base repository hash and name, owner, and number as the stable request identity.

src/Capacitor.Cli.Core/PullRequests/PullRequestSubjectDto.cs

PullRequestThreadDto.csModel inline review threads +42/-0

Model inline review threads

• Adds resolution and outdated state, file and line metadata, diff previews, root comments, counts, links, and availability.

src/Capacitor.Cli.Core/PullRequests/PullRequestThreadDto.cs

PullRequestWire.csValidate PR wire data and external links +69/-0

Validate PR wire data and external links

• Centralizes subject, cursor, timestamp, count, page, and response validation. It also constrains PR, check, and Markdown links before external opening.

src/Capacitor.Cli.Core/PullRequests/PullRequestWire.cs

Refactor (2) +159 / -175
AuthenticatedServerReads.csExtract reusable authenticated server read leases +149/-0

Extract reusable authenticated server read leases

• Introduces a generic authenticated channel lease manager supporting concurrent reads, sign-out retirement, authentication invalidation, redirect policy selection, and orderly asynchronous disposal.

src/Capacitor.App/Services/AuthenticatedServerReads.cs

ServerWorkContextSource.csReuse shared authenticated read infrastructure +10/-175

Reuse shared authenticated read infrastructure

• Replaces the source's custom HTTP lease implementation with AuthenticatedServerReads while preserving work-context behavior and adding authentication invalidation.

src/Capacitor.App/Services/ServerWorkContextSource.cs

Tests (11) +1493 / -2
FakePullRequestSource.csProvide deterministic PR reader test data +56/-0

Provide deterministic PR reader test data

• Adds a controllable fake source for links, overview responses, typed pages, failures, cancellation, and multi-page scenarios.

test/Capacitor.App.Tests.Unit/FakePullRequestSource.cs

PullRequestContextViewModelTests.csTest PR reader lifecycle and access behavior +185/-0

Test PR reader lifecycle and access behavior

• Covers foreground masking, stale-request rejection, transient grace, denial clearing, selection retention, page eviction, check precedence, recovery, and primary-repository selection.

test/Capacitor.App.Tests.Unit/PullRequestContextViewModelTests.cs

PullRequestViewSmokeTests.csSmoke-test persistent native PR views +61/-0

Smoke-test persistent native PR views

• Verifies lazy reader creation and reuse for active or ended sessions with or without terminals, while preserving Chat drafts and native hosts.

test/Capacitor.App.Tests.Unit/PullRequestViewSmokeTests.cs

ServerPullRequestSourceTests.csTest source recovery and authentication races +58/-0

Test source recovery and authentication races

• Verifies per-session three-404 settling, explicit retry reset, and safe disposal when authentication changes during client construction.

test/Capacitor.App.Tests.Unit/ServerPullRequestSourceTests.cs

Capacitor.Cli.Core.Tests.Unit.csprojInclude the canonical PR fixture in tests +3/-0

Include the canonical PR fixture in tests

• Copies the v1 pull-request contract bundle into the unit-test output directory.

test/Capacitor.Cli.Core.Tests.Unit/Capacitor.Cli.Core.Tests.Unit.csproj

CapacitorHttpContainerTests.csTest protected authenticated HTTP reads +24/-2

Test protected authenticated HTTP reads

• Confirms protected clients retain authentication and 401 recovery while refusing redirect targets.

test/Capacitor.Cli.Core.Tests.Unit/Http/CapacitorHttpContainerTests.cs

PullRequestClientTests.csTest PR protocol negotiation and validation +149/-0

Test PR protocol negotiation and validation

• Pins the fixture digest and exercises every typed route, discovery states, lease timing, backoff, same-origin enforcement, legacy admission, and malformed rows.

test/Capacitor.Cli.Core.Tests.Unit/PullRequests/PullRequestClientTests.cs

SpoolDrainLoopTests.csSupport protected reads in daemon HTTP fakes +3/-0

Support protected reads in daemon HTTP fakes

• Implements the new protected-read interface method in the spool-drain test client.

test/Capacitor.Cli.Daemon.Tests.Unit/Services/SpoolDrainLoopTests.cs

FixedCapacitorHttpClient.csSupport protected reads in fixed HTTP tests +3/-0

Support protected reads in fixed HTTP tests

• Adds a successful protected authenticated client result to the shared fixed test helper.

test/Capacitor.Tests.Helpers/FixedCapacitorHttpClient.cs

RecordingCapacitorHttpClient.csRecord protected HTTP client requests +3/-0

Record protected HTTP client requests

• Extends the shared recording helper to provide and track protected authenticated read clients.

test/Capacitor.Tests.Helpers/RecordingCapacitorHttpClient.cs

pull-request-reads-v1.jsonAdd the canonical PR reads v1 fixture +948/-0

Add the canonical PR reads v1 fixture

• Defines protocol-version errors, representative responses for every PR route, tolerant extension cases, malformed response cases, denial, and discovery negotiation examples.

test/fixtures/pull-request-reads-v1.json

Documentation (6) +1793 / -0
CHANGES.mdDocument the desktop linked-PR reader +20/-0

Document the desktop linked-PR reader

• Adds a change record describing the sidebar card, native reader, access leases, masking, stable pagination, compatibility behavior, and server rollout dependency.

docs/CHANGES.md

github-app-token-lifecycle-research.mdRecord GitHub App token lifecycle research +142/-0

Record GitHub App token lifecycle research

• Documents installation-token issuance, scoping, renewal, revocation, webhook reconciliation, and broker security implications.

docs/github-app-token-lifecycle-research.md

github-linked-pr-access-research.mdEvaluate linked-user authorization for PR reads +164/-0

Evaluate linked-user authorization for PR reads

• Explains why identity linking alone is insufficient and recommends a fail-closed repository-role check before tenant-served GitHub reads. It records capability probes and the delegated-user-token alternative.

docs/github-linked-pr-access-research.md

github-pr-context-preflight.mdRecord deployment and GitHub API preflight results +251/-0

Record deployment and GitHub API preflight results

• Captures PAT limitations, GitHub App permission checks, scoped live probes, allowed and denied user controls, cleanup, and remaining rollout validation.

docs/github-pr-context-preflight.md

2026-09-07-desktop-pr-context-design.mdSpecify desktop PR context architecture +922/-0

Specify desktop PR context architecture

• Defines the read-only experience, linked-user gate, wire contract, stable pagination, access retention, request budgets, compatibility, lifecycle behavior, and verification requirements.

docs/superpowers/specs/2026-09-07-desktop-pr-context-design.md

2026-09-07-github-app-pr-credentials-design.mdDesign tenant-scoped GitHub App credentials +294/-0

Design tenant-scoped GitHub App credentials

• Proposes a shared-proxy token broker with repository-restricted leases, tenant binding, renewal, revocation, pacing, and rollout requirements.

docs/superpowers/specs/2026-09-07-github-app-pr-credentials-design.md

@qodo-code-review

qodo-code-review Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Switching servers can leak old tokens ✗ Dismissed 🐞 Bug ⛨ Security
Description
RegisteredLaneAsync memoizes _lane even though its CapacitorServer, credential source, and
handlers are constructed using the URL of the first call. After a profile/server switch,
BorrowAsync supplies the new URL to PullRequestClient, but its request flows through the cached
handler, which applies a bearer resolved for the old server to the new origin.
Code

src/Capacitor.App/Services/AuthenticatedServerReads.cs[R42-45]

+        _lane ??= new ServiceCollection()
+            .AddSingleton(config)
+            .AddSingleton(profiles)
+            .AddSingleton(new CapacitorServer(url, config, profiles))
Relevance

●● Moderate

Security impact is plausible, but no closely matching server-switch credential precedent was found.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new shared read factory builds its provider only once with the first URL, whereas later borrows
explicitly accept a changed URL and create a channel using that changed URL. The cached provider's
credential selection is bound to CapacitorServer.Url, and its authorization handler attaches that
selected bearer to every outgoing request without checking the request origin.

src/Capacitor.App/Services/AuthenticatedServerReads.cs[40-52]
src/Capacitor.App/Services/AuthenticatedServerReads.cs[77-101]
src/Capacitor.Cli.Core/Auth/ResolvingCredentialSource.cs[41-54]
src/Capacitor.Cli.Core/Auth/UnauthorizedRecoveryHandler.cs[24-31]
src/Capacitor.Cli.Core/PullRequests/PullRequestClient.cs[8-10]},{: TBD

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`AuthenticatedServerReads<TChannel>` caches one DI service provider in `_lane`, even when a later borrow has a different server URL. The provider's `CapacitorServer`, credential source, and HTTP handlers remain bound to the first URL, while the newly created channel sends absolute requests to the new URL.

## Issue Context
A profile/server change must create an origin-specific authenticated lane. Retire and dispose each lane only after its active borrowers complete, so an in-flight read is not disrupted; do not reuse a handler chain whose credential source was selected for another origin.

## Fix Focus Areas
- src/Capacitor.App/Services/AuthenticatedServerReads.cs[40-52]
- src/Capacitor.App/Services/AuthenticatedServerReads.cs[77-102]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. JSON validation can drift by field ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
ValidJson repeatedly compares JsonElement.ValueKind directly for arrays, objects, nulls,
strings, and numbers instead of using the shared JsonElementExtensions predicates. Every
pull-request response passes through this recursive validator, so duplicated kind classification
affects all validated fields and nested payloads.
Code

src/Capacitor.Cli.Core/PullRequests/PullRequestWire.cs[R32-33]

+        if (root.ValueKind == JsonValueKind.Array) return root.EnumerateArray().All(ValidJson);
+        if (root.ValueKind != JsonValueKind.Object) return true;
Relevance

●●● Strong

Recent accepted findings consistently require shared JSON helpers for direct ValueKind checks.

PR-#479
PR-#497

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance rule 2270023 requires all JsonElement type and shape checks to use
JsonElementExtensions. The new recursive validator directly checks ValueKind throughout its
array, object, timestamp, count, and nested-object branches.

Rule 2270023: Use JsonElementExtensions helpers instead of direct JsonValueKind comparisons
src/Capacitor.Cli.Core/PullRequests/PullRequestWire.cs[32-44]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Replace direct `JsonElement.ValueKind` comparisons in recursive wire validation with the corresponding shared predicates.

## Issue Context
`ValidJson` recursively validates complete pull-request response payloads and currently duplicates JSON kind classification.

## Fix Focus Areas
- src/Capacitor.Cli.Core/PullRequests/PullRequestWire.cs[32-44]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Public read types are conflated ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
PullRequestRead.cs declares both the public PullRequestReadKind enum and the public generic
PullRequestRead<T> record even though the file name identifies only the record. These
independently consumed public models are not an enum-extension pair or an internal implementation
hierarchy, leaving the enum outside a matching source file.
Code

src/Capacitor.Cli.Core/PullRequests/PullRequestRead.cs[R3-5]

+public enum PullRequestReadKind { Ready, Stale, Unavailable, Restart, SubjectUnavailable, SignedOut, TransportFailure, InvalidProtocol }
+
+public sealed record PullRequestRead<T>(PullRequestReadKind Kind, T? Data = null, PullRequestSubjectDto? Subject = null,
Relevance

●●● Strong

Splitting independently public enum and record types is a deterministic compliance and
discoverability fix.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance rule 3162234 requires one public primary type per source file unless a documented
exception applies. The added file defines two public top-level types, while its filename matches
only PullRequestRead.

Rule 3162234: One primary type per file, with only narrow documented exceptions
src/Capacitor.Cli.Core/PullRequests/PullRequestRead.cs[3-5]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Place the public read-result enum and record in separate, correspondingly named source files.

## Issue Context
The new file contains two public primary types without satisfying an allowed same-file exception.

## Fix Focus Areas
- src/Capacitor.Cli.Core/PullRequests/PullRequestRead.cs[3-5]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Public capability types are conflated ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
PullRequestCapability.cs declares both the public PullRequestCapabilityKind enum and the public
PullRequestCapability record even though the file name identifies only the record. Neither
declaration is an allowed enum-extension pairing or an internal implementation hierarchy, so later
maintainers cannot locate each public model by its type name.
Code

src/Capacitor.Cli.Core/PullRequests/PullRequestCapability.cs[R3-5]

+public enum PullRequestCapabilityKind { Supported, Legacy, Unsupported, Unavailable, SignedOut, InvalidProtocol }
+
+public sealed record PullRequestCapability(PullRequestCapabilityKind Kind, int? Version = null, string? Reason = null, DateTime? RetryAt = null);
Relevance

●●● Strong

One-public-type-per-file is a deterministic maintainability fix and aligns with repository
organization conventions.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance rule 3162234 permits one public primary type per matching file, subject only to narrow
exceptions. This new file contains two public top-level types and only one matches its filename.

Rule 3162234: One primary type per file, with only narrow documented exceptions
src/Capacitor.Cli.Core/PullRequests/PullRequestCapability.cs[3-5]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Place each public capability type in its own correspondingly named source file.

## Issue Context
The enum and record are separate public primary types and do not match an allowed same-file exception.

## Fix Focus Areas
- src/Capacitor.Cli.Core/PullRequests/PullRequestCapability.cs[3-5]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (1)
5. JSON validation can drift by reader ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
DiscoverAsync and LegacyLinksAsync compare JsonElement.ValueKind directly for objects,
strings, arrays, and numbers instead of using the shared JsonElementExtensions predicates.
Protocol discovery and legacy pull-request parsing therefore maintain independent shape checks that
can diverge when the shared JSON handling changes.
Code

src/Capacitor.Cli.Core/PullRequests/PullRequestClient.cs[R34-35]

+                if (root.ValueKind != JsonValueKind.Object || !root.TryGetProperty("provider", out var provider)
+                    || provider.ValueKind != JsonValueKind.String || string.IsNullOrWhiteSpace(provider.GetString())) return Save(new(PullRequestCapabilityKind.InvalidProtocol));
Relevance

●● Moderate

Accepted JSON-helper precedents exist, but a recent matching direct-ValueKind finding was rejected.

PR-#479
PR-#497
PR-#484

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance rule 2270023 prohibits direct JsonElement.ValueKind comparisons when equivalent helpers
exist. The added client code directly compares object, string, array, and number kinds during
pull-request protocol parsing.

Rule 2270023: Use JsonElementExtensions helpers instead of direct JsonValueKind comparisons
src/Capacitor.Cli.Core/PullRequests/PullRequestClient.cs[34-38]
src/Capacitor.Cli.Core/PullRequests/PullRequestClient.cs[74-75]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Replace direct `JsonElement.ValueKind` comparisons with the corresponding shared `JsonElementExtensions` predicates.

## Issue Context
The new pull-request client performs object, string, array, and number checks directly in discovery and legacy response parsing.

## Fix Focus Areas
- src/Capacitor.Cli.Core/PullRequests/PullRequestClient.cs[34-38]
- src/Capacitor.Cli.Core/PullRequests/PullRequestClient.cs[74-75]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 61 rules
✅ Cross-repo context — repo relationships
  Explored: repo: kurrent-io/kcap-server (sha: 6fca12a6)
  Explored: repo: kurrent-io/kcap-deployments (branch: feat/desktop-pr-context, sha: 7074b044)
Review mode: 🧠 Deep: This is a dense, cross-cutting feature spanning authenticated HTTP/API contracts, native UI, workspace/session state, serialization, and multiple independent code paths, with substantial security and compatibility risk.

Grey Divider

Tip of the day
💡 Did you know, you can tweak Display preferences with a live preview to see your comment before it ships

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/Capacitor.Cli.Core/PullRequests/PullRequestClient.cs Outdated
Comment thread src/Capacitor.Cli.Core/PullRequests/PullRequestWire.cs Outdated
Comment thread src/Capacitor.Cli.Core/PullRequests/PullRequestCapability.cs Outdated
Comment thread src/Capacitor.Cli.Core/PullRequests/PullRequestRead.cs Outdated
Comment thread src/Capacitor.App/Services/AuthenticatedServerReads.cs
@linear-code

linear-code Bot commented Sep 8, 2026

Copy link
Copy Markdown

AI-2567

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 69f3dc2a1a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/Capacitor.App/ViewModels/PullRequestContextViewModel.cs Outdated
Comment thread src/Capacitor.App/ViewModels/PullRequestContextViewModel.Reads.cs
Test teardown owns every registered standalone worktree; shared paths let one
fixture delete another's repository. Await the in-flight server request before
testing permission cancellation.
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.

Read linked pull requests in the desktop workspace

1 participant