Skip to content

[comp] Production Deploy - #3549

Merged
Marfuen merged 3 commits into
releasefrom
main
Aug 5, 2026
Merged

[comp] Production Deploy#3549
Marfuen merged 3 commits into
releasefrom
main

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

This is an automated pull request to release the candidate branch into production, which will trigger a deployment.
It was created by the [Production PR] action.


Summary by cubic

Fixes the MCP/public-API policy content serialization bug and hardens policy editing/publishing consistency under concurrency. Also scopes knowledge base document actions to the authenticated organization and removes an unused endpoint.

  • Bug Fixes

    • Preserve TipTap content through the ValidationPipe by reading the raw body in UpdateVersionContentDto (CS-722).
    • When updating a draft policy’s content, also sync draftContent (non-empty only) to avoid stale “unpublished changes” and accidental reverts on publish-without-version.
    • updateVersionContent now runs inside a transaction, row-locks the policy, validates against in-transaction state, updates the version, and mirrors edits to Policy.draftContent (and content when editing the current draft version). Empty payloads no longer wipe the draft.
    • Standardize lock/write order to prevent deadlocks: write Policy first, then PolicyVersion in publish/accept flows.
  • Refactors

    • Resolve organizationId from auth context in knowledge base document and manual-answer handlers; ignore organizationId from the body.
    • Remove the runs/:runId/token endpoint.
    • Add targeted tests for org scoping, content preservation, draft sync, lock ordering, and race conditions.

Written for commit 4cbcdd2. Summary will update on new commits.

Review in cubic

github-actions Bot and others added 3 commits July 29, 2026 01:57
* fix(in-progress): [bug] mcp issue - serialization bug

## Problem
CloudconPTY Ltd

Client is attempting to update policy via MCP, however claude ran into an issue and points to a serialization bug in Comp AI:

"Retrying now with the same content.The call went through this time — but something's wrong. Look at what came back: the `content` field saved as **20 empty arrays** (`[[],[],...]`) instead of my 20 content nodes. The write landed (the `updatedAt` timestamp changed to just now), but the content didn't serialize correctly — the policy body may now be blank rather than holding the new text.

Let me verify exactly what's stored before doing anything else.This didn't work either, and I need to be upfront: the retry returned successfully but **corrupted the content instead of saving it.** Here's the actual state I just confirmed by re-reading the policy:

* The policy's `content` (its live body) is now **20 empty blocks** — effectively blank.
* The `currentVersion` content is also blank.
* The good news: your **original text is still intact** in the policy's `draftContent` field, untouched.

What's happening is a serialization bug in the Comp AI MCP write path: when I send the structured policy body, each content block arrives as an empty array `[]` rather than the actual heading/paragraph. So the write "succeeds" but lands empty. This is why I don't want to keep firing it — every attempt through this tool will keep blanking the `content` field the same way, and it won't ever land the real text. It's not something retrying fixes.

Because the policy was never published and is still a draft, the original wording surviving in `draftContent` means you likely haven't lost anything the editor shows — but I won't guarantee that, and importantly: **don't publish this policy until the body is restored**, or you'd publish a blank version.

Given the write path is broken, the reliable way to get the rewrite in is to paste it into the Comp AI policy editor directly, bypassing the integration entirely. The finished text is in my earlier message — I can re-send it as clean copy-pasteable text if that's easier.

How would you like to proceed?

1. I re-send the rewritten policy as plain text for you to paste into Comp AI's editor (surest fix — gets the correct new content in and overwrites the blank body).
2. I attempt to write the *original* text back into `content` so it's not blank — but I expect this to hit the exact same bug and stay empty, so I'd only do it if you want to confirm the behavior.
3. You raise the serialization issue with Comp AI support, since their MCP write endpoint is mangling structured content.

I'd recommend option 1. Want me to re-post the text?"

--- ticket comments (read the WHOLE thread and use the LATEST reconciled understanding — customers/CX often correct themselves, e.g. "my mistake, it works in chrome"; scope the bug to what is actually CONFIRMED now, not an earlier claim that was later retracted) ---
[redacted-email]: https://linear.app/compai/profiles/paul

hey so i re-checked the serialization bug you mention and it's actually already fixed in the current code we added a Transform decorator on the content field in the DTO a while back that prevents the empty array issue. the pipe that was causing `[[],[],...]` doesn't touch it anymore.

that said the customer now says claude doesn't see trycomp tools at all and can't connect to the MCP server, which sounds different from the content blank thing. i can't tell from the code if that's a real issue or maybe they just need to restart the claude app or reconnect. can you ask them: do they see the trycomp tools listed when they first open claude, or is it blank from the start? and when they try to use it what error do they get exactly something in the claude app or does it just hang? that'll help me figure out if it's mcp connection or something else
Unthread: Brendan Leung: I tried generating a new API key to use already as well​‌​
Unthread: Brendan Leung: I was using the Claude desktop app and tried starting a new chat and asking something like “list compliance tasks” which worked initially but encountered the first issue with the serialisation. Now, it doesn’t recognise anything from trycomp.​‌​
Unthread: Paul: The error here is often erroneous - are you using Claude Code? Can you go into the session and try to begin working?​‌​
Unthread: Brendan Leung: Hi <@U0936FZ6TFB|Paul>, any update on this? We're trying to update these policies ASAP​‌​
Unthread: Paul: Hi <@U07ET6LPSHK|Brendan Leung> just checking this​‌​
Unthread: Brendan Leung: Hey <@U0A64NBGY3S|Mark>, trying again by reconnecting to MCP server but seems like there's an issue connecting now - is this a known issue at the moment?​‌​
[redacted-email]: https://linear.app/compai/profiles/paul

Fix merged. Covers exactly what Brendan described.

**What was broken:** The API's validation pipeline was silently coercing each TipTap content node (heading, paragraph, etc.) into an empty array `[]` before saving. So a 20-node policy body became 20 empty arrays write "succeeded" but content was blank. The MCP path hit this the same as any other API caller.

**What the fix does:** Reads the raw content from the original request before that coercion runs. Content nodes now survive the pipeline intact.

**Does it cover their report?** Yes, exactly. The symptom they described `[[],[],...]` instead of actual content nodes is precisely what this fix corrects.

---

**What to tell Brendan:** The fix is shipped. He can retry updating his policy via MCP now content should save correctly. He'll want to verify the current policy body first (it may still have the 20 blank blocks from the earlier failed write) and re-send the correct content. His `draftContent` was untouched, so he can use that as the source if he needs the original text.
Unthread: Mark: Hey <@U07ET6LPSHK|Brendan Leung>, i have noticed that there is a comment from Engineering stating they have fixed the serialisation issue, are you able to try again and let me know?​‌​
Unthread: Mark: Hey <@U07ET6LPSHK|Brendan Leung>, this is currently in review with Engineering, so has made progress. I will follow up now with them to see if we can get this turned around today.​‌​
Unthread: Brendan Leung: Hey <@U0936FZ6TFB|Paul> any update on this issue?​‌​
[redacted-email]: fixed the serialization issue in the mcp write path for policy updates content was arriving empty because the structured blocks werent being serialized correctly before saving we patched it and tested it working now customer can use the integration again to update their policy
#3388
Unthread: Linked to Unthread ticket:
> [AI assistant edits resulted in incomplete sentences and incorrect formatting, unable to restore previous version #11108](https://compai.unthread.io/dashboard/inbox/all/conversations/f6dffd3d-3864-4027-bb97-10074eb8ea1c)
[redacted-email]: This comment thread is synced to a corresponding [thread in Slack](https://comp-ai-workspace.slack.com/archives/C09CV8JCGKD/p1783667450211219). All replies are displayed in both locations.

--- PREVIOUS FIX ATTEMPTS (this ticket was reopened 2x) ---
attempt 1: merged (PR #3388)
  came back because: Customer reports the serialization bug is still occurring when using Claude desktop app to ask for compliance tasks, and now the app doesn't recognize trycomp at all.
attempt 2: reopened but could not confirm: The serialization defect is real and precisely located in our code: main.ts:127-134 runs the global ValidationPipe with enableImplicitConversion, so class-transformer reads the reflected Array design-type of `content: unknown[]` and instantiates each TipTap node as `new Array()` with string keys, which Prisma/JSON serializes as `[]` — the customer's `[[],[],...]`. Current main already defeats it at create-policy.dto.ts:98 (`@Transform(({ obj }) => obj.content)`, inherited by UpdatePolicyDto via PartialType; I ran the existing spec against the identical pipe options and it passes), and I swept mechanism-first for residual paths: the only other policy-content write bypasses the pipe via `@Req().body` (policies.controller.ts:1268), org-chart takes `@Body() Record<string, unknown>` (native metatype → ValidationPipe skips), and every other object-array DTO field uses `@Type()` or a union type that reflects as Object — so no live path can still blank persisted JSON. The symptom actually live per the LATEST thread message ("reconnecting to MCP server but seems like there's an issue connecting now" / Claude sees no trycomp tools) is a different, runtime connect/tool-discovery claim I cannot prove from static code, and its only levers are the generated+published apps/mcp-server (never-touch) or the MCP OAuth/mcpOrgBinding path in hybrid-auth.guard.ts (§4 auth) — needs real run/log evidence, not a code guess.
  came back because: The customer reports the MCP server connection is still not working after the fix.
--- A previous fix for this ALREADY SHIPPED (merged to main) and the ticket came back, so the shipped fix is INSUFFICIENT. Do NOT conclude "already fixed" just because the code already contains that change — it is present and still not enough. Re-investigate the root cause, find the remaining gap the earlier attempt missed, and fix THAT. ---

## Fix
[Bug] MCP issue - serialization bug

## Verification
✅ added a regression test; suite green locally

* fix(in-progress): address cubic review

Address review findings.

* fix(in-progress): address cubic review

Address review findings.
Resolve organizationId from the authenticated request context in the document and manual-answer handlers (consistent with the list/save handlers), and remove the unused run-token endpoint.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Marfuen
Marfuen merged commit c03dab9 into release Aug 5, 2026
9 checks passed
@claudfuen

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 3.111.1 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants