Skip to content

feat(mobile): add edit and delete for own PR review comments - #6694

Merged
iscekic merged 19 commits into
mainfrom
kwf/app-pr-review-own-comment-crud-f555
Sep 28, 2026
Merged

iscekic merged 19 commits into
mainfrom
kwf/app-pr-review-own-comment-crud-f555

Conversation

@iscekic

@iscekic iscekic commented Sep 24, 2026 •

Copy link
Copy Markdown
Collaborator

Changelog for users

  • Comment actions on your own comment now offers Edit comment and Delete comment.
  • Edit comment opens a sheet showing the posted text in full, and Save updates the row in the discussion.
  • Delete comment asks one confirmation; confirming removes the comment, and deleting an inline thread's root removes the thread.
  • Comments written by other authors show no Edit comment and no Delete comment.
  • A failed edit shows an inline error, keeps the typed body, and leaves Save available to retry.
  • A failed delete restores the comment in its place and shows a Retry prompt.
  • While the app is confirmed offline, Save and Delete show the retryable failure copy instead of starting a write the app pauses.

Changelog for maintainers

  • Adds githubPrReview.updateComment and deleteComment, dispatching on kind to pulls.* (review) or issues.* (conversation); delete confirms the PR is still reachable before treating a provider 404 as success, so an already-deleted comment stays idempotent while a missing PR / repo / App access surfaces as a real failure.
  • A provider 404 on an own comment is terminal on the client: a failed edit shows the deleted-comment copy and keeps Save down, and a failed delete reports the terminal copy instead of offering a retry that cannot succeed.
  • updateComment runs the UGC terms gate before any GitHub write, and both mutations take number so the overview can be invalidated after a write.
  • Adds optimistic applyCommentBodyUpdate / applyCommentRemoval reducers with snapshot rollback and settle invalidation; the writes carry no operation-ledger key because both are idempotent.
  • Adds a per-PR deleted-comment-retention store that filters a deleted comment out of refetched pages and discounts the Discussion badge, reconciled once the overview count falls below the delete's baseline.
  • retainConversationAcrossMounts now takes firstPageLoaded, so a loaded-but-empty first page stays the source of truth and deleting the last conversation comment empties the discussion.
  • Adds the comment-edit formSheet route and PrCommentEditSheet; useComposerInlineError takes a surface selecting the edit-specific bad-request and retryable copy.
  • CommentRow replaces the disabled self-moderation trio with Edit/Delete only when both callbacks are supplied for the viewer's own comment; read-only provider rows keep the prior menu.
  • Review first the delete retention/badge interaction in the PR review screen and the confirmed-offline gates in the discussion tab and the edit sheet.
  • updateComment and deleteComment now check comment ownership on the server (assertViewerOwnsComment), not only in the mobile row. A caller that bypasses the app cannot edit or delete another author's comment. The guard reads the comment author and the caller's own GitHub login, and refuses a mismatch with FORBIDDEN.
  • MCP exposure: services/kilo-mcp/catalog.json now lists githubPrReview.updateComment and deleteComment, so this PR must justify the exposure of a comment delete to MCP agents.
  • The exposure is intentional. The catalog publishes every router mutation wholesale (apps/web/src/scripts/mcp-catalog/catalog.ts), and CI fails on catalog drift, so a hand-written exclusion does not exist. Main already publishes 80 delete/remove/revoke/cancel mutations, including githubPrReview.removeReaction.
  • Both paths act only on the caller's own comment. assertViewerOwnsComment refuses another author's comment server-side, so an MCP agent can change only a comment that the caller's own GitHub token already lets it change. The use case is cleanup: an agent that posted a review comment on the caller's behalf can correct its text or remove it.

E2E proof

Owner request

Surface: the mobile app (apps/mobile), the PR review page.

The PR review page creates a comment. Add read, update and delete for the user's own comments.

Evidence: apps/mobile/src/components/pr-review/pr-review-comment-composer.tsx creates a comment. pr-review-comment-composer-screen.tsx hosts it. pr-review-discussion-tab.tsx renders the discussion.

Requirements:

  • Read: the user opens an existing own comment and sees its full text.
  • Update: the user edits an own comment, and the discussion shows the new text.
  • Delete: the user deletes an own comment, after one confirmation step.
  • Own comments only. A comment from another author offers no edit action and no delete action.
  • The three actions follow the existing comment UI and the design language of this surface.
  • Show a visible failure when a write fails. Never leave a silent no-op.

Proof: live screenshots of read, update and delete on the PR review page, plus one failed write.

[e3] delete an own comment after one confirmation (default Android): create a conversation comment, Comment actions > Delete comment, exactly one confirmation dialog ('Delete comment?'), Delete, and the… — android emulator-5554: after Comment actions > Delete comment exactly one confirmation dialog is present (e3-confirm-dialog.txt / jev-drive-1790189111342.log: title 'Delete comment?', message 'This comment will be deleted from the pull request.', buttons Cancel/Delete), Delete removes the comment (e3-final-gone.txt: no 'kwf-del-final' text; e3-after-delete.txt: no 'kwf-delete-me' text) and it stays gone after a fresh reload of the pr-review state (e3-final-stays-gone.txt, e3-stays-gone.txt: zero 'kwf-' comment bodies). The parked scene cannot be used as-is: e3-final-scene.log shows its…

[e3] delete an own comment after one confirmation (default Android): create a conversation comment, Comment actions > Delete comment, exactly one confirmation dialog ('Delete comment?'), Delete, and the… — prior/e3-confirm-dialog.png

[e1] read then update an own comment (default Android): create a conversation comment, see its full text in the discussion (read), open Comment actions > Edit comment, the sheet shows the full text… — banked from the progress ledger at the turn cap

[e1] read then update an own comment (default Android): create a conversation comment, see its full text in the discussion (read), open Comment actions > Edit comment, the sheet shows the full text… — prior/e1-read-sheet.png

[e3] ux-check: own-comment overflow lists Edit comment / Delete comment / Report content / Cancel; another author's comment and a deleted-author comment show neither — android emulator-5604, declared state pr-review on real GitHub #6054 Discussion tab. Own arm: e3-discussion.txt shows the rows text="kilo-code-bot" (other author) and text="iscekic" beside text="e9 second comment" (the viewer's own); opening Comment actions on that own row yields a sheet with exactly text="Edit comment", text="Delete comment", text="Report content", text="Cancel" (e3-own-overflow.txt, e3-own-overflow.png). Other-author arm: opening Comment actions on the kilo-code-bot row yields text="Report content", text="Report user", text="Mute", text="Block", text="Cancel"…

[e3] ux-check: own-comment overflow lists Edit comment / Delete comment / Report content / Cancel; another author's comment and a deleted-author comment show neither — prior/e3-deleted-overflow.png

[e3] ux-check: own-comment overflow lists Edit comment / Delete comment / Report content / Cancel; another author's comment and a deleted-author comment show neither

[e3] ux-check: own-comment overflow lists Edit comment / Delete comment / Report content / Cancel; another author's comment and a deleted-author comment show neither — prior/e3-own-overflow.png

[e9] posts two conversation comments and deletes the older one — Scripted scene MISSed because the declared state's real PR was unavailable while github-stub was up; stopped the stub, restored state pr-review and hand-drove on real PR #6054 (posted 'e9 first comment' then 'e9 second comment', deleted the older via Comment actions > Delete comment > 'Delete comment?' > Delete): e9-after-delete.txt contains text="e9 second comment" with 0 occurrences of 'e9 first comment' (present before the delete in e9-two-comments.txt) and e9-real-pr-comments.log lists only '5799399364 | iscekic | e9 second comment'; UX audit: zero defects.

[e9] posts two conversation comments and deletes the older one — prior/e9-after-delete.png

[e1] update failure is visible and the text is kept (default Android) — needs:fault: the update write fails (transport/5xx). — android emulator-5554: with nextjs down (e1-fault.log fault.sh: nextjs killed (port 6100 refuses), the corrected replay e1.replay.json ends SCENE e1 OK in e1-scene.log (the expected Couldn't save your comment copy assert passed) and e1-failure-state.txt shows the sheet still open after the failed write with the typed text kept (class="android.widget.EditText" text="-x") and Save still usable (content-desc="Save" ... clickable="true" enabled="true"); nothing was written and the comment list is unchanged; failure-state still captured as e1-failure-state.png for the visual reviewer.

[e1] update failure is visible and the text is kept (default Android) — needs:fault: the update write fails (transport/5xx). — prior/e1-failure-state.png

[e17] ux-check: Failed write (server rejection): the edit sheet shows a visible inline error and keeps the typed body and Save available for retry; a failed delete restores the row and shows a retryable… — android emulator-5554, PR #6054; with nextjs down the edit sheet showed the inline error 'fetch failed: java.io.IOException: unexpected end of stream on http://127.0.0.1:6100/...' and the toast 'Couldn't save your comment. Check your connection and try again.' with Button "Save" still enabled and the typed body kept (Cancel opened 'Discard comment?'), and the failed delete restored the 'kwf-read-edit' row then showed the 'Something went wrong'/'Couldn't delete your comment. Check your connection and try again.' alert whose Button "Retry" re-ran the delete instead of a silent…

[e17] ux-check: Failed write (server rejection): the edit sheet shows a visible inline error and keeps the typed body and Save available for retry; a failed delete restores the row and shows a retryable… — e17-edit-failed-toast.png

[e19] ux-check: Offline delete: with the app confirmed offline, confirming Delete shows the failure feedback and leaves the comment row in place rather than optimistically vanishing. — android emulator-5554, PR #6054 Discussion tab: with the app confirmed offline (banner TextView "No internet connection", radio off) the own row "e9 second comment" showed one confirmation dialog (e19-confirm.txt), and the digest right after confirming Delete shows TextView "Couldn't delete your comment. Check your connection and try again." together with TextView "e9 second comment" and android.view.View "Discussion, 3" (e19-delete-failed.log) — failure feedback shown and the row left in place, never optimistically removed; the scripted confirm also ended SCENE e19 OK with both…

[e19] ux-check: Offline delete: with the app confirmed offline, confirming Delete shows the failure feedback and leaves the comment row in place rather than optimistically vanishing. — e19-delete-failed.png

[e17] ux-check: Failed write (server rejection): the edit sheet shows a visible inline error and keeps the typed body and Save available for retry; a failed delete restores the row and shows a retryable…

[e17] ux-check: Failed write (server rejection): the edit sheet shows a visible inline error and keeps the typed body and Save available for retry; a failed delete restores the row and shows a retryable… — e17-delete-retry-prompt.png

[e18] ux-check: Offline edit: with the app confirmed offline (offline banner shown before opening), tapping Save in the edit sheet shows the retryable inline copy immediately with no indefinite spinner… — android emulator-5554, PR #6054; radio off, the 'No internet connection' banner was on the Discussion before the edit sheet opened, tapping Save with the body edited showed 'Couldn't save your comment. Check your connection and try again.' at once with Button "Save" and Button "Cancel" enabled (no spinner), and Cancel opened the 'Discard comment?' gate (e18-offline-edit.log, e18-offline-banner.png, e18-offline-inline-copy.png); no UX-DEFECT in the digests.

[e18] ux-check: Offline edit: with the app confirmed offline (offline banner shown before opening), tapping Save in the edit sheet shows the retryable inline copy immediately with no indefinite spinner… — e18-offline-banner.png

[e7] empty discussion: no comment management anywhere (default Android) — needs:seed: the seeded PR has no review threads and no conversation comments. — android; state.sh pr-review STATE HIT, hermetic stub fixture kilo-stub/discussion-empty#3 opened, harvested replay: 'SCENE e7 OK' with digest showing 'No discussion yet' / 'No review threads or conversation comments on this pull request.' and no 'Comment actions' (still e7.png).

[e7] empty discussion: no comment management anywhere (default Android) — needs:seed: the seeded PR has no review threads and no conversation comments. — e7.png

[e15] ux-check: update dismisses the sheet and shows the new text without a full reload (android emulator-5606) — Changed the body to 'kwf-e10-read-comment edited v2' and tapped Save on real GitHub (#6401): e15-update.log line 1 'SCENE e15 OK' and the final digest shows the Discussion row text="kwf-e10-read-comment edited v2" with the 'Edit comment' sheet header absent, i.e. the sheet dismissed and the row updated in place with no full reload and no duplicate loading indicator; no UX defect.

[e15] ux-check: update dismisses the sheet and shows the new text without a full reload (android emulator-5606) — e15.png

[e14] Read: Edit comment formSheet shows the posted comment text in full — Tapped Comment actions > Edit comment on the viewer's own comment; the formSheet EditText (content-desc="Comment body") carries the full row text ending 'end-marker' identical to the discussion row, and the Save button is content-desc="Save" ... enabled="false" while the body is unchanged (same in e14-edit.txt for the short comment); UX audit: zero defects.

[e14] Read: Edit comment formSheet shows the posted comment text in full — e14-edit.png

[e10] read + update own comment on the PR review page (android emulator-5606) — Ran on real GitHub (#6401) after github-stub.sh stop + github-user-token.sh seed + github-installation.sh, because the pack's stub serves no comment PATCH (404 'stub: unhandled PATCH'); the edit sheet opened with the full body (e10-real-read-sheet.txt: text="kwf-e10-read-comment" beside text="Edit comment"), appending ' edited' (e10-real-dirty-sheet.txt: text="kwf-e10-read-comment edited") and Save made the sheet dismiss and the Discussion row show text="kwf-e10-read-comment edited" (e10-real-updated.txt), confirmed server-side by e10-github-verify.log ('kwf-e10-read-comment…

[e10] read + update own comment on the PR review page (android emulator-5606) — e10-real-read-sheet.png

[e12] needs:fault:nextjs down, delete own comment then Retry after recovery (default Android) — android; viewer comment kwf-e12-real-del seeded on #6054; with nextjs down (fault.sh) the confirmed Delete showed 'Something went wrong' + 'Couldn't delete your comment. Check your connection and try again.' + Retry (e12-error.txt); Cancel left the row present (e12-rollback.txt); after fault.sh up nextjs, Retry removed it — e12-final.txt shows Discussion count 3 with no kwf-e12-real-del.

[e12] needs:fault:nextjs down, delete own comment then Retry after recovery (default Android) — e12-error.png

[e18] ux-check: Offline edit: with the app confirmed offline (offline banner shown before opening), tapping Save in the edit sheet shows the retryable inline copy immediately with no indefinite spinner…

[e18] ux-check: Offline edit: with the app confirmed offline (offline banner shown before opening), tapping Save in the edit sheet shows the retryable inline copy immediately with no indefinite spinner… — e18-offline-inline-copy.png

[e3] ux-check: own-comment overflow lists Edit comment / Delete comment / Report content / Cancel; another author's comment and a deleted-author comment show neither

[e3] ux-check: own-comment overflow lists Edit comment / Delete comment / Report content / Cancel; another author's comment and a deleted-author comment show neither — e3-other.png

Follow-ups (not changed here)

  • not proved live: needs:fault:nextjs down with needs:seed: a PR whose Discussion holds one viewer-authored conversation comment - the viewer deletes that comment while the backend is down: expected the row returns and a 'Something went wrong' dialog with a Retry button appears; after the backend is back, Retry removes the comment. The fault, not a tap, is the trigger, so the verifier drives the taps; the comment can be seeded with the same empty-Discussion fixture s1 uses, posting one comment first. (no capture cited it)
  • not proved live: needs:seed: a PR whose topmost Discussion row is another author's comment (temporary fixture: the hermetic stub's kilo-stub/discussion-conversation-only#2, whose comments are by dave and erin) - the viewer opens that row's actions: expected the sheet offers Report content and offers no Edit comment and no Delete comment (no capture cited it)
  • not proved live: needs:seed: same empty-Discussion fixture - the viewer posts one comment, opens Edit comment and sees its full text, appends text and saves: expected the sheet shows the full comment text and the Discussion then shows the edited text (no capture cited it)
  • not proved live: needs:seed: same empty-Discussion fixture - the viewer posts two conversation comments and deletes the older one: expected the older comment's text is gone and the newer comment's text is still shown (no capture cited it)
  • not proved live: read, update and delete an own inline review comment (default Android) — needs:seed: the seeded PR has an unresolved review thread whose first comment is authored by the signed-in user and is reachable from the Discussion. Expands the thread, edits that own review comment and saves, then deletes it with the one confirmation. (no capture cited it)
  • not proved live: ux-check: Open the overflow on the viewer's own comment: the sheet lists Edit comment, Delete comment, Report content, Cancel; open the overflow on another author's comment (and on a deleted-author comment): no Edit comment and no Delete comment appear. (no capture cited it)
  • not proved live: ux-check: Read: tapping Edit comment opens the formSheet showing the posted comment text in full — scroll the body field to its last line and confirm it matches the discussion row, with Save disabled while the body is unchanged. (no capture cited it)
  • not proved live: ux-check: Update: change the body and tap Save; the sheet dismisses and the discussion row shows the new text without a full reload. (no capture cited it)

Owner manual verification

Owner verification is pending; these checks did not pass automatically.

  • owner-manual: layout/colour/spacing/loading-indicator appearance is the visual reviewer's judgement on this run's captures; my captures for it are e3-composer.png, e3-comment-created.png, e3-comment-actions-sheet.png, e3-confirm-dialog.png, e3-comment-deleted.png, e4-comment-created.png, e4-confirm-dialog.png, e4-delete-failed-alert.png, e4-comment-still-present.png, e4-recovery-deleted.png. No layout shift, duplicate spinner, dead space or missing feature state was observable in the behavior digests: the delete is optimistic (row removed instantly, restored on failure) and the failure path carries an actionable Retry.

Open findings (not fixed here)

  • [e2] needs:seed: the app is on a PR whose Discussion carries no conversation comments (temporary fixture: the hermetic stub's kilo-stub/discussion-empty#3, started with e2e/github-stub.sh start <email>; harness-only, outside the product diff) - the viewer posts one conversation comment and deletes
  • [e2] $KILO_WORKFLOW/e2e/appium.sh script /home/igor_kilocode_ai/.local/share/kwf/sections/app-pr-review-own-comment-crud-f555/e2e-mobile-app/repro-e2.json --out /home/igor_kilocode_ai/.local/share/kwf/sections/app-pr-review-own-comment-crud-f555/e2e-mobile-app/repro-e2
  • [e2] post then delete last conversation comment to empty discussion: android emulator-5554, stub github-stub kilo-stub/discussion-empty#3: after the post-and-delete scene the comment remained (SCENE e2 MISS absent 'e2e last comment' (still visible after 10s); android.widget.TextView e2e last comment
  • not fully verified: some optional checks did not run
  • not proved live: p1-updated.png is no longer on the host that took it, so no publish can carry it
  • not proved live: p12-edit-sheet.png is no longer on the host that took it, so no publish can carry it
  • not proved live: p5-confirm.png is no longer on the host that took it, so no publish can carry it
  • not proved live: p8-save-fail.png is no longer on the host that took it, so no publish can carry it
  • the '## E2E proof' section carries no log excerpt, so nothing shows the change was driven end to end

… (kwf app-pr-review-own-comment-crud-f555/s2)
…ete confirm (kwf app-pr-review-own-comment-crud-f555/s4)
… (kwf app-pr-review-own-comment-crud-f555/s5)
…the discussion (retention must not resurrect it) (kwf app-pr-review-own-comment-crud-f555/c1)
…y CTA this surface's other actions use (kwf app-pr-review-own-comment-crud-f555/c2)
…e (kwf app-pr-review-own-comment-crud-f555/ux1)
…em (kwf app-pr-review-own-comment-crud-f555/ux2)
@iscekic
iscekic marked this pull request as draft September 24, 2026 13:54
Comment thread apps/web/src/routers/github-pr-review-router.ts Outdated
@kilo-code-bot

kilo-code-bot Bot commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Executive Summary

The ownership fix (assertViewerOwnsComment) correctly closes the server-side gap raised in review, but the PR also newly publishes a data-deleting githubPrReview.deleteComment mutation to the Kilo MCP catalog without justifying why an MCP agent may call it.

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
services/kilo-mcp/catalog.json 10571 Newly published MCP mutation githubPrReview.deleteComment deletes data and is not justified in the PR.
Files Reviewed
  • services/kilo-mcp/catalog.json - 1 issue
  • apps/web/src/routers/github-pr-review-router.ts - ownership guard verified (prior review remark fixed)
  • apps/web/src/routers/github-pr-review-router.test.ts - guard coverage verified
  • .kilo/skills/kilo-mcp/SKILL.md - generated catalog-count refresh

Fix these issues in Kilo Cloud

Previous Review Summaries (4 snapshots, latest commit 18904c2)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 18904c2)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental delta since the prior review is a clean merge of main; the PR's own changed files are untouched and both prior 404-handling findings remain fixed at current HEAD.

Files Reviewed (3 files, current-HEAD verification)
  • apps/mobile/src/lib/pr-review/mutation-error-display.ts - prior edit-surface 404 finding re-verified fixed
  • apps/mobile/src/lib/pr-review/discussion/use-pr-comment-crud-mutations.ts - prior 404-terminal finding re-verified fixed
  • apps/web/src/routers/github-pr-review-router.ts - prior delete-404 reachability check re-verified fixed

The only incremental change since 88174f7 is a clean merge of main (unrelated coding-plans work); no PR-owned source changed, so there are no new findings. The two previously reported issues are resolved and were not re-raised as duplicates.

Previous review (commit 88174f7)

Status: No Issues Found | Recommendation: Merge

Files Reviewed (8 files)
  • apps/mobile/src/components/pr-review/discussion/discussion-thread-resolve-toggle.tsx
  • apps/mobile/src/lib/pr-review/comment-trailing-controls.ts
  • apps/mobile/src/components/pr-review/discussion/comment-row.touch-target.test.tsx
  • apps/mobile/src/components/pr-review/discussion/discussion-thread.touch-target.test.tsx
  • apps/mobile/src/lib/pr-review/comment-trailing-controls.test.ts
  • apps/mobile/src/lib/pr-review/discussion/use-pr-comment-crud-mutations.ts - prior 404-terminal finding re-verified fixed
  • apps/mobile/src/lib/pr-review/mutation-error-display.ts - prior edit-surface 404 finding re-verified fixed
  • apps/web/src/routers/github-pr-review-router.ts - prior delete-404 reachability check re-verified fixed

The only delta since 347499b is a clean merge of main, whose PR-visible change is a tap-target constant rename with equivalent geometry; the fix commits' files are otherwise untouched.

Previous review (commit 347499b)

Status: No Issues Found | Recommendation: Merge

Executive Summary

The incremental fix commit resolves both prior findings — own-comment 404s are now terminal on the edit surface and deleteComment verifies PR reachability before treating a provider 404 as an idempotent success — and introduces no new issues.

Files Reviewed (11 files, incremental commit 347499b)
  • apps/mobile/src/components/pr-review/composer-inline-error.tsx
  • apps/mobile/src/components/pr-review/discussion/pr-comment-edit-sheet.tsx
  • apps/mobile/src/components/pr-review/discussion/pr-comment-edit-sheet.test.tsx
  • apps/mobile/src/components/pr-review/pr-review-submit.tsx
  • apps/mobile/src/lib/pr-review/discussion/use-pr-comment-crud-mutations.ts
  • apps/mobile/src/lib/pr-review/discussion/use-pr-comment-crud-mutations.test.ts
  • apps/mobile/src/lib/pr-review/mutation-error-display.ts
  • apps/mobile/src/lib/pr-review/mutation-error-display.test.ts
  • apps/web/src/routers/github-pr-review-router.ts
  • apps/web/src/routers/github-pr-review-router.test.ts
  • services/kilo-mcp/catalog.json (generated; inspected)

Previous review (commit d2d59dc)

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 1
Issue Details (click to expand)

WARNING

File Line Issue
apps/mobile/src/lib/pr-review/discussion/use-pr-comment-crud-mutations.ts 96 Editing a comment deleted elsewhere returns a provider 404, classified retryable, so the edit sheet shows the generic retry copy with Save live and the intended "can't be edited / may have been deleted" copy is never reached.

SUGGESTION

File Line Issue
apps/web/src/routers/github-pr-review-router.ts 1954 deleteComment maps every provider 404 to { deleted: true }, so a missing PR/repo or missing GitHub App access reports a false success until the settle refetch.
Files Reviewed (31 source/test files plus 86 locale catalogs)
  • apps/web/src/lib/github-pr-review/mutations.ts
  • apps/web/src/lib/github-pr-review/mutations.test.ts
  • apps/web/src/routers/github-pr-review-router.ts - 1 issue
  • apps/web/src/routers/github-pr-review-router.test.ts
  • apps/mobile/src/app/(app)/pr-review/[owner]/[repo]/[number]/_layout.tsx
  • apps/mobile/src/app/(app)/pr-review/[owner]/[repo]/[number]/comment-edit.tsx
  • apps/mobile/src/components/pr-review/composer-inline-error.tsx
  • apps/mobile/src/components/pr-review/composer-inline-error.test.tsx
  • apps/mobile/src/components/pr-review/discussion/comment-row.tsx
  • apps/mobile/src/components/pr-review/discussion/comment-row.test.tsx
  • apps/mobile/src/components/pr-review/discussion/discussion-thread.tsx
  • apps/mobile/src/components/pr-review/discussion/discussion-thread.test.tsx
  • apps/mobile/src/components/pr-review/discussion/discussion-thread-resolve-toggle.tsx
  • apps/mobile/src/components/pr-review/discussion/pr-comment-edit-sheet.tsx
  • apps/mobile/src/components/pr-review/discussion/pr-comment-edit-sheet.test.tsx
  • apps/mobile/src/components/pr-review/discussion/pr-review-discussion-list.tsx
  • apps/mobile/src/components/pr-review/discussion/pr-review-discussion-list.test.tsx
  • apps/mobile/src/components/pr-review/discussion/pr-review-discussion-list.mounted.test.tsx
  • apps/mobile/src/components/pr-review/pr-review-discussion-tab.tsx
  • apps/mobile/src/components/pr-review/pr-review-discussion-tab.test.tsx
  • apps/mobile/src/components/pr-review/pr-review-discussion-tab.test-helpers.tsx
  • apps/mobile/src/lib/pr-review/discussion/review-discussion-types.ts
  • apps/mobile/src/lib/pr-review/discussion/review-discussion-reducers.test.ts
  • apps/mobile/src/lib/pr-review/discussion/use-pr-comment-crud-mutations.ts - 1 issue
  • apps/mobile/src/lib/pr-review/discussion/use-pr-comment-crud-mutations.test.ts
  • apps/mobile/src/lib/pr-review/discussion/use-pr-review-discussion-threads.ts
  • apps/mobile/src/lib/pr-review/discussion/use-pr-review-discussion-threads.test.ts
  • apps/mobile/src/lib/pr-review/mutation-error-display.ts
  • apps/mobile/src/lib/pr-review/mutation-error-display.test.ts
  • apps/mobile/src/i18n/catalog-parity.test.ts
  • apps/mobile/src/i18n/locales/en.json
  • 85 other apps/mobile/src/i18n/locales/*.json catalogs

Fix these issues in Kilo Cloud


Reviewed by deepseek-v4.1-flash · Input: 0 · Output: 0 · Cached: 0

Review guidance: REVIEW.md from base branch main

iscekic and others added 3 commits September 25, 2026 15:11
…-comment-crud-f555

# Conflicts:
#	apps/mobile/src/components/pr-review/discussion/pr-review-discussion-list.mounted.test.tsx
#	apps/mobile/src/components/pr-review/discussion/pr-review-discussion-list.tsx
#	apps/mobile/src/i18n/catalog-parity.test.ts
…before an idempotent delete

Kilobot review on #6694:

- WARNING: classifyPrReviewMutationError falls through to retryable for
  NOT_FOUND, so editing a comment deleted elsewhere showed the generic
  retryable copy with Save live and the intended commentEditUnavailable
  copy stayed unreachable. commentCrudFailure now returns the surface's
  terminal copy for a 404, and mutationErrorDisplay maps an edit-surface
  404 to the new terminal `not-found` kind, which keeps Save down in
  PrCommentEditSheet.

- SUGGESTION: every provider 404 was reported as a successful delete, but
  classifyGitHubHttpError maps a missing PR / repo / App access to the same
  NOT_FOUND. deleteComment now confirms the PR is still reachable before
  reporting the delete as done; otherwise the 404 propagates.
@iscekic iscekic added the human-ready The PR is ready for human review. label Sep 25, 2026
@iscekic
iscekic marked this pull request as ready for review September 25, 2026 13:49
…-comment-crud-f555

One conflict in discussion-thread.tsx: this branch extracts ResolveToggle into discussion-thread-resolve-toggle.tsx, and main renames the tap-target module and the compact 44pt slop constant. Keep the extraction, and let the extracted file import COMPACT_H11_HIT_SLOP_DP from @/lib/a11y/tap-target, which is main's renamed name and keeps the touch-target test green.
@iscekic
iscekic marked this pull request as draft September 25, 2026 19:07
@iscekic
iscekic marked this pull request as ready for review September 25, 2026 19:07
@iscekic
iscekic marked this pull request as draft September 25, 2026 20:10
@iscekic
iscekic marked this pull request as ready for review September 25, 2026 20:10
…-comment-crud-f555

# Conflicts:
#	apps/mobile/src/app/(app)/pr-review/[owner]/[repo]/[number]/_layout.tsx
#	apps/mobile/src/i18n/catalog-parity.test.ts
@iscekic iscekic added merge-by-human the merge bot routed this PR to a human and removed human-ready The PR is ready for human review. labels Sep 26, 2026

@eshurakov eshurakov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning — comment edit/delete have no server-side ownership check.

updateComment / deleteComment (apps/web/src/routers/github-pr-review-router.ts:1894,1934) forward owner / repo / commentId straight to pulls.* / issues.*. The "own comment" rule is enforced only by the mobile UI; the procedures themselves do not compare the target comment's author to ctx. A caller who bypasses the UI (for example a collaborator with push access) can still edit or delete another author's comment through these procedures. GitHub's own token scoping still blocks non-collaborators and there is no cross-repo path, but if "own comment only" is a requirement it should be checked server-side rather than in the UI.

The mobile row shows Edit and Delete only on the viewer's own comment.
The procedures did not compare the comment author with the caller, so a
caller that skipped the app could change another author's comment.

`assertViewerOwnsComment` reads the comment author and the caller's own
GitHub login, then refuses a mismatch with FORBIDDEN. The viewer login
comes from a live read, because a GitHub rename would leave the recorded
login stale. A 404 on the comment read is not an ownership verdict: the
guard reports the comment as missing, so the idempotent delete path
stays unchanged.
@iscekic

iscekic commented Sep 28, 2026

Copy link
Copy Markdown
Collaborator Author

Fixed in 334cc8a. The remark is valid. updateComment and deleteComment passed the comment id to GitHub and relied on the mobile row for the "own comment" rule. The server compared nothing.

The router now calls assertViewerOwnsComment before each write. The guard reads the target comment and the caller's own GitHub login, then compares the two logins. A mismatch throws FORBIDDEN with "You can only edit or delete your own comments."

Two details decide the shape:

  • The viewer login comes from a live read, not from the credential's recorded githubLogin. A GitHub rename would leave the recorded value stale, and the guard would refuse the user's own comment.
  • A 404 on the comment read is not an ownership verdict. The guard reports the comment as missing, and each procedure keeps its behavior. deleteComment stays idempotent.

Verification: apps/web/src/routers/github-pr-review-router.test.ts passes 89 tests. Five new cases cover the non-owner edit, the non-owner delete, a login that differs only in case, a deleted author account, and a 404 comment read. tsgo --noEmit exits 0.

Comment thread services/kilo-mcp/catalog.json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-by-human the merge bot routed this PR to a human

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants