mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-06 21:05:21 +02:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The issue-comments API (`POST /api/issues/:id/comments`) attributes each comment to the run that created it via `created_by_run_id`, a foreign key into `heartbeat_runs` > - In multi-agent local control-plane usage, board/session clients sometimes forward an `X-Paperclip-Run-Id` that is not a real run row — a non-UUID client request id, a synthetic string, or a since-deleted run > - That value was written straight to the FK column, so the insert died with a Postgres FK violation and the endpoint returned HTTP 500, breaking agent coordination > - This PR resolves the run id defensively before insert: reject non-UUID shapes, verify the row exists for the company, and null out anything unresolvable while logging a warning > - The benefit is that a bad run-id header degrades gracefully to an unattributed comment (201) instead of a 500, so comment creation stays up ## Linked Issues or Issue Description No public issue exists; describing inline (bug): **What happened:** `POST /api/issues/:id/comments` returns HTTP 500 when the request carries an `X-Paperclip-Run-Id` that does not correspond to a row in `heartbeat_runs` (non-UUID value, synthetic client id, or deleted run). The value is written to the `created_by_run_id` FK, and Postgres rejects the insert with a foreign-key violation (SQLSTATE 23503). **Expected:** the comment is created (HTTP 201); an unresolvable run id is dropped to `null` rather than failing the request. **Impact:** in multi-agent usage, comment creation — and the agent coordination that depends on it — fails whenever a client forwards a run id that isn't a live run. ## What Changed - Add `resolveCommentCreatedByRunId(dbOrTx, companyId, runId)` — trims and validates UUID shape, then checks existence in `heartbeat_runs` scoped to the company; returns `null` for missing/invalid ids. - `addComment` now resolves the run id through that helper before insert and logs a warning when a supplied run id is dropped. - Add embedded-Postgres regression tests for the three cases (non-UUID header, unknown UUID, valid run id). ## Verification - `pnpm --filter server test issues-service` — the new `issueService.addComment createdByRunId` block passes. - Cases covered: non-UUID header → 201, `createdByRunId: null`; UUID absent from `heartbeat_runs` → 201, `null`; valid run id present for the company → preserved. ## Risks Low. Purely defensive — valid run ids are still preserved, only unresolvable ones are nulled. Adds one indexed, tenant-scoped `SELECT` per comment insert. ## Model Used Claude Opus 4.8 (extended thinking), via the Paperclip PR-triage cockpit, produced the added regression tests and this description. The original implementation is by @digitalflanker-ux; the author's model is unspecified. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [ ] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above (related: #4795 same fix; #8065 sibling FK-guard on the activity-log path) - [x] I have either (a) linked existing issues OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links - [ ] My branch name describes the change and contains no internal Paperclip ticket id - [ ] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [ ] I have updated relevant documentation to reflect my changes - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com> Co-authored-by: Andrew Aymeloglu <aaymeloglu@gmail.com>