Skip to content

fix(integrations): close regressions found in the final validation sweep - #6764

Merged
waleedlatif1 merged 6 commits into
stagingfrom
chore/integration-final-validation
Aug 16, 2026
Merged

fix(integrations): close regressions found in the final validation sweep#6764
waleedlatif1 merged 6 commits into
stagingfrom
chore/integration-final-validation

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

An independent read-only audit of the eight integrations merged to staging today — one cold agent per integration, each researching vendor docs from scratch — found defects in every one. Most are side effects of the surgery those PRs performed on already-shipped code, which is exactly what the sweep was looking for.

Every fix has a regression test, and each test was individually verified to fail when its fix is reverted.

Data loss / destructive

  • Cloudflare — shipped workflows lost their filters. The merged PR reassigned six shipped subBlock ids. Stored block state is keyed by the old id, so list_dns_records sent no filters and returned the entire zone with success: true — and any downstream delete_dns_record fan-out would then target every record. Fixed by restoring the shipped id on the read side and renaming the write side instead, chosen by blast radius: a lost read filter is destructive, a lost write field just omits from a PATCH.
  • Cloudflare — update_ruleset_rule unbound WAF managed rulesets. PATCH is a replace; an omitted action_parameters dropped action_parameters.id on an execute rule, detaching the managed ruleset and every override under it. It now refuses rather than silently tearing down the rule it edits.
  • Cloudflare — a hidden control disabled live rules. enabled was one advanced subBlock shared by all four rule operations; advanced controls serialize before their condition is evaluated, so a value set while drafting silently disabled a live WAF or rate-limiting rule.
  • Cloudflare — name renamed live DNS records when carried from another operation.
  • Okta — a blank name still overwrote a stored group name through the LLM path. The earlier fix guarded only the block.

Broken on the default path

  • Entra — update_user failed on every call left at its default. accountEnabled defaults to '', the mapper omitted the key, and finalInputs = {...inputs, ...transformedParams} left the raw '' to reach Graph as a non-boolean. Same tri-state defect already fixed for forceChangePasswordNextSignInWithMfa; visibility had it too.
  • Cloudflare — Access domain was unconditionally optional but is required for self_hosted (the dropdown default), ssh, vnc, rdp. Added saas_app/target_criteria; dropped dash_sso, which has no request variant.

Silent wrong results

  • Datadog — list_monitors inherited Create Monitor's tag filter, returning a filtered list as if complete.
  • ServiceNow — fields carried both a JSON body and a projection on the three legacy generic operations. The regression test named for this fed already-JSON and could not fail; it now feeds a real projection.
  • Splunk — cancel_search_job reported failure on success, parsing an XML body as JSON.
  • Okta — sendEmail === true dropped a string 'true', silently skipping the deactivation email on LLM and API-triggered runs.

Security

  • MSSQL — WRITETEXT/UPDATETEXT were reachable through the read-only path. \bupdate\b cannot match UPDATETEXT — there is no word boundary after update.
  • CrowdStrike — repeated-query ids built ~68 KB query strings at the published caps, past typical proxy limits. Chunked at 4 KB rather than lowering vendor-published caps.

Also

Splunk count=0 unbounded read, Splunk pagination totals, the nobody placeholder that reintroduced the namespace bug by copy-paste, Okta cursor/activate controls split per operation, ServiceNow sysparm_having syntax, two ServiceNow required controls no longer pre-seeded with consequential values (Move Change State defaulted to moving a change backwards; Approve/Reject defaulted to approve), Datadog block outputs reconciled with tool outputs, and 16 escaped apostrophes corrupting the published Entra docs.

Decisions worth reviewer attention

  • Only one Entra scope was removed (User.Read.All). Directory.Read.All and GroupMember.ReadWrite.All were proposed for removal and verified still requiredGET /subscribedSkus accepts neither of our license scopes, and group-post-members does not accept Group.ReadWrite.All. A test now asserts both stay.
  • Splunk behavior change: an explicit 0 is now sent for autoCancel/maxCount/dispatch*, where it was previously dropped. Correct per Splunk (auto_cancel=0 = never cancel) but semantic, not just a NaN guard.
  • Two Cloudflare renames were not reverted (certificateStatus, dnsOrder) because reverting would re-open a real leak. Recovering those stored values needs a state migration; nothing at the block level can do it.
  • Not changed, deliberately: csrutil/reg/eventlog are real read-tier RTR commands (the swagger prose is stale and there is no enum on base_command); Cloudflare's Access policy endpoint targeting stays nested, because the reusable endpoint rejects precedence; Okta's activated output keeps its name to avoid orphaning saved references.

Verification

type-check clean, biome clean, 41 test files / 820 tests passing, tool-metadata:check, integration-catalog:check, docs:check and check:api-validation all pass. Artifacts regenerated with no unrelated drift.

An independent read-only audit of the eight integrations merged to staging
today found defects in every one, most of them side effects of the surgery
those PRs performed on already-shipped code.

Data loss and destructive paths:
- cloudflare: restore the shipped subBlock ids on read filters so existing
  workflows keep their DNS/zone/purge filters. Losing them made
  list_dns_records return the entire zone with success: true, which a
  downstream delete fan-out would then target. The colliding write controls
  are renamed instead, chosen by blast radius.
- cloudflare: refuse an update_ruleset_rule that would tear down the rule it
  edits. PATCH is a replace, so an omitted action_parameters unbound the WAF
  managed ruleset and every override under it.
- cloudflare: split the hidden `enabled` control so a value set while drafting
  can no longer disable a live WAF or rate-limiting rule.
- cloudflare: stop `name` leaking into update_dns_record and renaming a live record.
- okta: stop a blank name overwriting a stored group name via the LLM path.
  The block guard covered only the UI.

Broken on the default path:
- microsoft_ad: update_user sent accountEnabled: "" on its own default, so
  every call left at "No Change" failed. Same tri-state defect already fixed
  for forceChangePasswordNextSignInWithMfa; `visibility` fixed alongside it.
- cloudflare: `domain` is required for self_hosted (the default app type),
  ssh, vnc and rdp; add saas_app/target_criteria and drop dash_sso, which has
  no request variant.

Silent wrong results:
- datadog: list_monitors inherited Create Monitor's tag filter and returned a
  filtered list as if complete.
- servicenow: `fields` carried both a JSON body and a projection on the three
  legacy generic operations. The regression test for this fed already-JSON and
  could not fail; it now feeds a real projection.
- splunk: cancel_search_job reported failure on success by parsing an XML body
  as JSON; readSplunkJson now tolerates it.
- okta: sendEmail === true dropped a string 'true', silently skipping the
  deactivation email.

Security:
- mssql: add writetext/updatetext/readtext to the statement screen. \bupdate\b
  cannot match UPDATETEXT, so both were reachable through the read-only path.
- crowdstrike: chunk repeated-query ids. At the published caps a single request
  built a ~68 KB query string, past typical proxy limits.

Also: splunk count=0 unbounded read, splunk pagination totals, the `nobody`
placeholder that reintroduced the namespace bug by copy-paste, okta cursor and
activate controls split per operation, servicenow sysparm_having syntax and two
required controls no longer pre-seeded with consequential values, datadog block
outputs reconciled with tool outputs, and 16 escaped apostrophes that corrupted
the published Entra docs.

One scope removed from microsoft_ad (User.Read.All). Directory.Read.All and
GroupMember.ReadWrite.All were proposed for removal and verified still required;
a test now asserts they stay.
@vercel

vercel Bot commented Aug 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Aug 16, 2026 4:20am

Request Review

@cursor

cursor Bot commented Aug 16, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Touches destructive paths (CrowdStrike batched deletes, Cloudflare DNS/ruleset/Access controls, MSSQL write guards) and shipped workflow state (Cloudflare subBlock ids/migrations); incorrect mapping could still cause silent data loss or over-broad API calls.

Overview
Closes defects found across Cloudflare, CrowdStrike, Datadog, Entra ID, Okta, ServiceNow, Splunk, and MSSQL after a post-merge validation sweep—mostly regressions from recent integration refactors, with regression tests for each fix.

Cloudflare restores shipped subBlock ids for read filters (name, type, content, etc.) so saved workflows don’t list whole zones; write controls use dedicated ids (updateRecordName, updateRuleEnabled, separate R2 vs ruleset cursors). Rule updates refuse empty action_parameters on execute rules, split create vs update enabled, tighten Access app types/domain/saasApp/targetCriteria, and add a migration that drops staging-only legacy filter ids.

CrowdStrike batches by-id GET/DELETE calls under a ~4 KB URL budget with partial-delete error reporting; MSSQL read-only validation adds UPDATETEXT/WRITETEXT/READTEXT; RTR docs/commands add ifconfig/users.

Datadog / Entra / Okta / ServiceNow / Splunk fix param mappers (leaked filters, tri-state ''undefined, per-operation cursors/toggles), numeric coercion (no NaN on the wire), split/conflicting subBlocks, outputs, OAuth scope cleanup (User.Read.All removed), and integration docs/catalog updates.

Reviewed by Cursor Bugbot for commit 4395da3. Configure here.

@greptile-apps

greptile-apps Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR performs a broad regression sweep across eight integrations, restoring persisted block-state compatibility and correcting request mapping, response parsing, pagination, destructive-update safeguards, and generated metadata.

  • Separates operation-specific block controls and adds migration or compatibility handling where saved workflow state is affected.
  • Tightens Cloudflare, CrowdStrike, MSSQL, Okta, ServiceNow, Splunk, Datadog, and Entra request/response behavior.
  • Adds focused regression coverage and regenerates integration documentation and tool metadata.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains, and the previously reported Splunk and CrowdStrike issues are fixed or invalidated by the current code and thread acknowledgments.

Important Files Changed

Filename Overview
apps/sim/tools/splunk/utils.ts The dispatch reader now extracts SIDs only from complete Splunk response envelopes while strict JSON parsing remains in place for search results.
apps/sim/app/api/tools/crowdstrike/query/operations.ts By-ID requests are URL-budgeted and destructive batch failures preserve confirmed committed IDs without overstating partial successes.
apps/sim/blocks/blocks/cloudflare.ts Cloudflare operation controls and parameter mappings are split to prevent unrelated stored values from entering destructive update requests.
apps/sim/blocks/blocks/servicenow.ts ServiceNow body fields and response projections are separated by operation to avoid conflating request payloads with query parameters.
apps/sim/lib/workflows/migrations/subblock-migrations.ts Saved workflow sub-block identifiers are migrated for renamed integration controls to preserve persisted configuration.
apps/sim/app/api/tools/mssql/utils.ts Read-only SQL validation now recognizes additional mutating statement families that previously bypassed keyword matching.

Reviews (5): Last reviewed commit: "fix(splunk): read the dispatch XML envel..." | Re-trigger Greptile

Comment thread apps/sim/tools/splunk/utils.ts Outdated
Comment thread apps/sim/app/api/tools/crowdstrike/query/operations.ts
Comment thread apps/sim/tools/cloudflare/update_ruleset_rule.ts
Comment thread apps/sim/blocks/blocks/datadog.ts Outdated
Comment thread apps/sim/blocks/blocks/okta.ts
…ike deletes

Narrows readSplunkJson's non-JSON tolerance to XML. The dispatching and
job-control endpoints answer in XML, but a body that is neither empty nor XML
was meant to be JSON, so swallowing its parse failure handed get_search_results
an empty envelope and reported a lost result set as a search with zero events.

Annotates a batched CrowdStrike delete that fails partway with the IDs its
earlier batches already removed. Falcon cannot roll those back, so a bare
failure left the caller unable to tell what was gone and a blind retry
re-targeted IDs that no longer existed.

Registers the Cloudflare subblock-ID migration the registry-stability check
requires. The suffixed read-filter IDs never shipped in a release and every
block already materializes the restored IDs, so they are dropped rather than
renamed onto values the collision guard would discard anyway.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

Pushed 906b23f addressing both Greptile P1s, plus the Check block registry invariants CI failure.

Splunk — malformed responses became empty results (P1). readSplunkJson's non-JSON tolerance now stops at XML rather than swallowing every parse failure, so a truncated result payload surfaces as an error instead of a successful search with zero events.

CrowdStrike — chunk failure hid prior deletions (P1). A batched DELETE that fails partway now reports the IDs its earlier batches already removed, that they were not rolled back, and that only the remainder should be retried. GET is unchanged — a partial read commits nothing.

CI — Cloudflare subblock-ID stability. The check flagged seven IDs removed by the read-filter restore. They are registered as _removed_ rather than renames: all seven were introduced in #6740 and appear in no release tag (verified against v0.8.2, where name/type/content/proxied/tags are the shipped IDs this PR restores), so no deployed workflow carries them. A rename could not recover a value in any case — block state materializes an entry for every declared subblock, not just the active operation's, so the restored IDs are always already present and migrateBlockSubblockIds' collision guard would discard the source value while leaving the stale key parked in state. cursor split into r2Cursor/rulesetCursor and has no single replacement.

Each of the three fixes has a regression test that was individually verified to fail when its fix is reverted.

An execute rule sent an explicit empty action_parameters object past the new
guard, because presence was checked rather than emptiness. `{}` is the same
payload Cloudflare's schema default produces, so it unbound the managed ruleset
the guard exists to protect.

Datadog's new List Monitors pagination used a bare `Number()`, so a typo or an
unresolved reference in either advanced field reached Datadog as a literal NaN
— the pattern this same sweep fixed for Entra `top` and the Splunk numerics.

Okta's block still marked the group name required on update, blocking a
description-only update that the tool, its merge helper, and the API all accept.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

Comment thread apps/sim/app/api/tools/crowdstrike/query/operations.ts Outdated
Comment thread apps/sim/tools/splunk/utils.ts Outdated
Comment thread apps/sim/app/api/tools/crowdstrike/query/operations.ts Outdated
…ke commit list

Splitting the XML tolerance out of readSplunkJson into readSplunkDispatchJson
puts it only on the three dispatching and job-control tools that need it. The
results path can no longer read any non-JSON body as an empty envelope, so a 2xx
HTML interstitial surfaces instead of reporting a search that matched nothing.
The dispatch reader anchors on the one documented `<response>` root, so an
interstitial fails there too.

A batched delete now records the IDs Falcon echoed in `resources` rather than
the IDs that were requested. A batch can answer 200 while reporting per-ID
failures, and naming those as deleted told the caller to drop still-live
indicators from the retry.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor 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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 15de5c2. Configure here.

Comment thread apps/sim/app/api/tools/crowdstrike/query/operations.ts
…d request

A 2xx envelope carrying per-ID errors is a partial success, not a failure —
failedWithoutResources fails the operation only when nothing came back at all.
The batched path already reports it exactly as a single request does, with
deletedIds naming what Falcon confirmed and errors naming what it refused. Pin
that so the contract is not mistaken for a swallowed failure.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor 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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 0531d3c. Configure here.

Comment thread apps/sim/tools/splunk/utils.ts Outdated
A dispatch answering in the documented XML form was replaced with an empty
object, so create_search_job and dispatch_saved_search threw a missing-sid error
after the remote job had already been created — stranding a job the caller could
no longer poll or cancel. The envelope is now projected onto the same `{ sid }`
shape output_mode=json produces, so the search ID survives.

Matching only the opening tag also accepted a body cut off mid-transfer, which
on a cancellation reported a truncated response as a successful cancel. The
pattern now spans the closing tag, so a truncated envelope falls through to
JSON.parse and throws.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor 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.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 4395da3. Configure here.

@waleedlatif1
waleedlatif1 merged commit aeb5624 into staging Aug 16, 2026
30 checks passed
@waleedlatif1
waleedlatif1 deleted the chore/integration-final-validation branch August 16, 2026 04:25
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.

1 participant