fix(integration-ever-works,docs): #11096 review findings (canonical content hash, one-way idea reconcile, webhook warning, OCR cap docs)
Four CodeRabbit findings from the develop → stage PR #11096, each verified against the code and fixed in its own commit.
1. Canonical content hash (CodeRabbit 4308331572, Major)
Problem: contentJsonHash hashed JSON.stringify(contentJson). PostgreSQL jsonb (and MySQL json) return the page with its object keys reordered: by length, then bytewise, so "text" comes before "type". The hash of the generated content never matched the hash of the page read back, so editedSince was always true. snapshot(..., editedSince) then skipped the snapshot window and wrote one DocumentVersion per Ever Works body write on stage/prod.
Fix: the hash input is now a canonical serialization: keys sorted at every depth, array order kept, undefined properties dropped, undefined array items written as null (what JSON.stringify does). String/SQLite text handling is unchanged.
Stored hashes: jHash is kept in the link snapshot across syncs, so a hash stored before this change is compared once with the new canonical hash.
- On PostgreSQL/MySQL those old hashes already never matched, so the first write after deploy does what every write did before.
- On SQLite, a link can get at most one extra version on its next Ever Works body write.
- A mismatch only ever causes an extra snapshot, never a skipped one, so no Gauzy edit can be lost. After that write the canonical hash is stored and the window applies again.
Tests:
ever-works-docs-content.spec.ts:- a page reordered like jsonb (also in its string form) hashes the same as the generated page;
- real edits, array order and value types still change the hash.
ever-works-docs.db.spec.ts: an inbound write to a page stored with jsonb key order stays within the window, so there is 1 version, not 2.- Before the fix, the jsonb-order tests fail (hash mismatch; 2 versions instead of 1). After it, they pass.
2. One-way idea reconcile (CodeRabbit 4308331583, Minor)
Problem: say Ever Works refuses a dismiss/restore with 422 because the idea already has the wanted status (an earlier move went through, but its answer was not recorded). The reconcile ran only when ideas sync from Ever Works. Under gauzy_to_ew the code fell through to the refusal path: it wrote the status back to the task, logged dismiss_refused as a conflict, and every later push sent the same move again.
Fix: the move is now recorded on the link in that case in both directions. Ever Works' idea is applied to Gauzy only when ideas sync inbound.
Test: in ever-works-ideas.service.spec.ts, under gauzy_to_ew:
- nothing is applied to Gauzy (no
TaskUpdateCommand, the EW-side rename is not taken); - the link records
dismissedwith Ever Works' version, and nodismiss_refusedis logged; - the next push sends no dismiss.
It fails before the fix and passes after.
3. Webhook-kept warning on disconnect (CodeRabbit 4308331563, Minor)
Problem: the connect wizard ignored { success: true, webhookDeleted: false }.
Fix: the wizard now shows a warning nb-alert, the same pattern the component already uses for other warnings, with the new i18n key EVER_WORKS.SETTINGS.DISCONNECT_WEBHOOK_KEPT in the plugin's en.json. The message tells the admin to revoke the key in Ever Works (Settings → API keys), which disables its webhooks. It describes reconnecting to the same tenant as a retry, not a guarantee.
Follow-up commit 01c565e4cf (Greptile and CodeRabbit on this PR): POST /connections now also returns earlierWebhookDeleted (optional, additive) when a reconnect resumed a connection still holding a subscription its disconnect could not delete. The wizard clears the warning only when that same connection comes back with earlierWebhookDeleted === true. Another Ever Works tenant gets a new connection id and a failed retry returns false, so in both cases the warning stays. Commit b1f333f394 tracks a set of kept connection ids, so a later disconnect of another connection that deleted its own subscription does not clear the warning about an earlier kept one.
Tests:
ever-works-connect.component.spec.ts: the alert shows after the disconnect and stays on the way to a new key. Three reconnect cases follow: only the same connection with its subscription confirmed deleted clears it; a failed retry or another tenant keeps it.ever-works-connection.db.spec.ts: a reconnect returnsearlierWebhookDeletedtrue or false; a plain connect returns no such field. The existingwebhookDeleted: truetest now also checks that no alert is shown. The new test fails before the fix and passes after.
Follow-up, not in this PR: the settings page's disconnect also ignores webhookDeleted. It navigates away right after, so showing the warning there needs navigation state.
4. OCR page cap docs (CodeRabbit 4308331554, Minor)
Fix: the README now describes the actual parsing. A follow-up commit, 805c66eaa2, states the exact rule: the digits after optional whitespace and a sign count, and a result that is not a finite number of at least 1 falls back. parseIntEnv uses Number.parseInt for every integer variable in the docs plugin config, on purpose, so 100pages → 100, 2.5 → 2, and empty/0/negative/non-numeric values → 20. No code change. The docs plugin has no strict integer validation anywhere else.
Test runs
Run with NODE_OPTIONS="--experimental-vm-modules --max-old-space-size=6144":
integration-ever-works: 42/42 suites, 759/759 tests passintegration-ever-works-ui: 54/54 tests pass in 4 suites.ever-works-settingsandever-works-pagefail to load becausengx-cookie-service(declared inpackages/ui-core/package.json) is missing from the local node_modules. This is an environment problem, not caused by this change.
🤖 Generated with Claude Code
Summary by cubic
Fixes four review findings from the develop → stage PR #11096 in the Ever Works integration and its docs plugin.
Bug fixes
- Docs sync now hashes page content in canonical form (object keys sorted at every depth), so the key reordering PostgreSQL
jsonband MySQLjsondo on read no longer makes every Ever Works body write count as an edit and keep an extraDocumentVersion. A hash stored before this change can still add one extra version on its next write. - A dismiss/restore that Ever Works already applied (422 refusal) is now recorded on the link under
gauzy_to_ewsync too, instead of writing the status back to the task and loggingdismiss_refusedon every push. Ever Works' idea is still only applied to Gauzy when ideas sync inbound. - The connect wizard now tracks the connections whose disconnect left a webhook subscription in Ever Works (
webhookDeleted: false) and shows a warning until the same connection reconnects andPOST /connectionsconfirms the subscription is gone (earlierWebhookDeleted: true). Reconnecting to another tenant, a failed retry, or a disconnect that deleted its own subscription keeps the warning. - The docs README now states how
GAUZY_DOCS_OCR_MAX_PAGESis parsed (Number.parseInt): leading digits count (100pagescaps at 100,+2pagesat 2,2.5at 2), anything else falls back to 20. No code change.