Skip to content

chore(release): promote release to master - #42101

Merged
appsmith-smithes[bot] merged 25 commits into
masterfrom
release
Aug 7, 2026
Merged

chore(release): promote release to master#42101
appsmith-smithes[bot] merged 25 commits into
masterfrom
release

Conversation

@appsmith-smithes

@appsmith-smithes appsmith-smithes Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Description

Promotes the release branch into master.

Commits included

Automation

/ok-to-test tags="@tag.All"

Communication

Should the DevRel and Marketing teams be notified?

  • Yes
  • No

Warning

Workflow run: https://github.com/appsmithorg/appsmith/actions/runs/31170311824
Commit: bef6ea3
Cypress dashboard.
Tags: @tag.All
Spec:
It seems like no tests ran 😔. We are not able to recognize it, please check workflow here.


Fri, 07 Aug 2026 10:32:58 UTC

subrata71 and others added 25 commits July 29, 2026 20:26
…oS) (#42064)

## Summary
- npm's **bundled** `tar` in the Docker base image
(`/opt/node/lib/node_modules/npm/node_modules/tar`) was `<= 7.5.16`,
flagged by **CVE-2026-59873** (critical, node-tar gzip-bomb DoS; fixed
in `tar@7.5.19`).
- Node 24.x ships npm 11.16/11.17 (tar `<= 7.5.16`), so a plain rebuild
stays vulnerable. This pins **`npm@11.18.0`** — the first npm release
bundling patched **`tar@7.5.19`** — in `deploy/docker/base.dockerfile`.

Linear: https://linear.app/appsmith/issue/APP-15736

## Notes
- Canonical CE change; syncs to EE. EE validation PR:
appsmithorg/appsmith-ee#9391
- Base-image change verified on the (identical) EE base image: `npm -v`
= `11.18.0`, bundled `tar` = `7.5.19`, CVE-2026-59873 no longer
reported.
- Base-image-only change: the `ok-to-test` Cypress matrix builds on
`base-ce:release`, so it does not exercise this change directly.

## Test plan
- [x] Base image rebuilt from branch; `npm -v` = `11.18.0` and bundled
`tar` = `7.5.19`
- [x] Image scan: CVE-2026-59873 no longer reported at the npm tar path
- [ ] App image builds on the new base (RTS `npm install` succeeds)

## Automation
/ok-to-test tags="@tag.All"

<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30451625675>
> Commit: 23e0957
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30451625675&attempt=2"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Wed, 29 Jul 2026 14:24:20 UTC
<!-- end of auto-generated comment: Cypress test results  -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Updated the Node.js environment to use a newer npm version, addressing
a security vulnerability in bundled tooling.
* Improved command resolution and refreshed the npm cache during setup.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
…k hidden datasource reuse (GHSA-p37g-mfwx-3r9f) (#42066)

## Description

fix(security): Datasource authorization bypass through import and fork
hidden datasource reuse (GHSA-p37g-mfwx-3r9f)

> **CE PR.** The EE validation PR listed below already ran the full EE
> suite, Cypress included, and came back green. Merge this CE PR first;
the
> hourly CE→EE sync then carries the fix into EE.

<!-- Smithes will fill from commit messages -->

### Vulnerability

| Field | Value |
|-------|-------|
| **GHSA** |
[GHSA-p37g-mfwx-3r9f](https://github.com/appsmithorg/appsmith/security/advisories/GHSA-p37g-mfwx-3r9f)
|
| **CVE** | Not assigned |
| **CVSS** | 8.1 (high) |
| **CWE** | CWE-863 |
| **Affected component** | Datasource authorization bypass through
import and fork hidden datasource reuse |

### Exposure Analysis

<!-- Smithes will fill from triage report -->

### Fix

<!-- Smithes will fill from plan -->

### CE/EE sync

<!-- Smithes will fill from check_ce_ee output -->

Merge this PR first. The hourly CE→EE sync propagates it to EE.

The linked EE validation PR is then refreshed from EE `release` and
re-tested.

### EE validation

EE validation PR: appsmithorg/appsmith-ee#9393

EE CI status at the time this PR was opened: **passing**
(ci-test|ci-test-limited, ci-test-result|ci-test-limited-result green).

### Disclosure

> **Do not merge until advisory is ready for disclosure coordination.**
>
> After merge:
> 1. Confirm fix is in release branch
> 2. Coordinate with security team on disclosure timeline
> 3. Update advisory with patched version and publish
> 4. Notify reporter

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30476127335>
> Commit: ca50f01
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30476127335&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Wed, 29 Jul 2026 18:44:22 UTC
<!-- end of auto-generated comment: Cypress test results  -->

## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No

---------

Co-authored-by: appsmith-smithes[bot] <appsmith-smithes[bot]@users.noreply.github.com>
## Summary

Adds Hacktron AI configuration to enable automated security code review
on every PR with Appsmith-specific context.

### Files added

- **`.hacktron/rules.md`** — Project rules giving Hacktron deep
understanding of Appsmith's security model:
- Public disclosure policy (no PoCs or exploitation steps in public PR
comments)
  - Authorization model (service-layer ACL, not repository-level)
  - Git/filesystem safety invariants
  - SSRF/egress control boundaries
  - XSS/browser security boundaries
  - Mass assignment and policy mutation risks
  - CI supply chain attack surface
  - CSRF, sessions, and redirect safety
  - Multi-tenant cache isolation requirements
- Intended datasource behavior (editors write queries — that's not
injection)

- **`.hacktron/config.yaml`** — Scan configuration:
  - Excludes markdown-only PRs (no exploitable code)
  - `hacktron-exclude` label as maintainer escape hatch
- Gates on `critical` severity during calibration week, then escalate to
`high`

### Why this matters

Hacktron learns from project rules and triage feedback. Without rules,
it doesn't know that:
- Repository methods intentionally omit ACL checks (service layer
enforces)
- RFC1918 access is intentional for self-hosted datasource connectivity
- App editors writing JS/SQL is intended functionality, not injection
- React text interpolation is safe

This will significantly reduce false positives while ensuring real
vulnerabilities (BOLA, path traversal, command injection, SSRF bypasses)
are caught.

### Public disclosure safeguard

Since this is a public repository, `rules.md` includes an explicit
disclosure policy instructing Hacktron to never publish exploitation
details, PoC payloads, or step-by-step reproduction in public PR
comments. Full details remain in the private Hacktron dashboard.

### Next steps after merge

1. Review the auto-generated threat model after first scan
2. Actively triage findings for 1 week (calibrate the model)
3. Escalate `fail_on.severity` from `critical` to `high`
4. Upload architecture docs and past CVE lessons to Hacktron dashboard
5. Connect Slack notifications
6. Add `.hacktron/**` to CODEOWNERS

<!-- This is an auto-generated comment: Cypress test results  -->
> [!WARNING]
> Tests have not run on the HEAD
7f4be3a yet
> <hr>Wed, 29 Jul 2026 18:56:56 UTC
<!-- end of auto-generated comment: Cypress test results  -->


Fixes
https://linear.app/appsmith/issue/APP-15738/integrate-hacktron-ai-security-review-and-optimize-configuration

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation / Security**
* Added security scanning configuration defining rule sourcing behavior,
PR exclusion via a dedicated label, Markdown scan exclusions, and
severity escalation expectations.
* Introduced a comprehensive security review ruleset outlining required
authorization checks, injection/execution safety, outbound request/SSRF
reporting, and client-side XSS boundaries.
* Included guidance to minimize noisy findings and avoid public
disclosure in documentation-only scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
…message (#42053)

Fixes APP-15731

Slack thread that prompted this:
https://theappsmith.slack.com/archives/C09GSB3APNU/p1784892702257989

## Why

A customer's push to a self-hosted GitLab was rejected. The ticket ran
for three days with support checking branch protection, push rules and
deploy-key permissions in turn, because Appsmith never showed the
reason. It could not: the reason was thrown away before it was ever
logged.

JGit reports a rejected push in two separate places.
`RemoteRefUpdate.getMessage()` carries the terse report-status reason,
which for every server-side hook is the same literal `pre-receive hook
declined`. The explanation an operator actually needs — "GitLab: You are
not allowed to push code to protected branches on this project", a
push-rule violation, a secret-scanning block — travels on the sideband
channel and is reachable only through `PushResult.getMessages()`. We
read the first and dropped the second, then replaced the failure with a
hardcoded guess: *"make sure you don't have any rules enabled on the
branch X"*. No log level recovered it.

That same shape — swallow the real error, emit a static string — recurs
across the git flows. This PR fixes the class, not just the instance.

## What changed

**The remote's own words now reach both the logs and the user.**
`FSGitHandlerCEImpl.summarisePushResult` captures the sideband response,
logs it once with repo, ref and remote, and carries it to
`GitFSServiceCEImpl`, which puts it in the error the user sees instead
of the guess. When the remote sends nothing back, the message names what
to check rather than asserting a cause.

**Stack traces survive.** Around 20 sites used `log.error("...",
e.getMessage())`. SLF4J only captures a stack trace when the `Throwable`
is the final argument, so these produced one line and nothing else.

**Silent recovery is now visible.** `resetHard` logged a message and
returned `false`, and the caller ignored it. After a rejected push
nobody could tell whether the local rollback worked, so a commit could
exist locally and nowhere else with no trace.

**Lock lifecycle is diagnosable.** Contention, retry exhaustion and
release logged nothing. "Another git operation is in progress" had no
diagnostics at all. Per-attempt contention is at `debug` so a blocked
operation does not emit 20 warnings; a single warning is raised when the
retries run out.

**Auto-commit stops failing invisibly.** It runs in the background, so
eligibility errors logged at `debug` and rejected pushes logged not at
all were effectively undetectable. `GitAutoCommitHelperImpl` also logged
"is not allowed" unconditionally *before* the eligibility check, so
every successful auto-commit logged the opposite of what happened.

**Correlation ids** (artifact, ref, repo, workspace) added to existing
git error logs.

## Behaviour changes

Three genuine bugs surfaced during the audit and are fixed here:

- The rejection check tested for `REJECTED_OTHERREASON`; JGit's enum is
`REJECTED_OTHER_REASON`. The branch was dead, so any rejection whose
message was not literally "pre-receive hook declined" fell through and
**was reported to the user as a successful push** while the commit never
left the server.
- Two `Mono.error(error)` results in the merge flows were constructed
but never returned, so an `AppsmithException` was replaced by a generic
one.
- The checkout guard compared a `GitRefDTO` to a `String` and so never
matched, leaking JGit's raw `Ref <name> already exists` to the user
instead of Appsmith's message.

The user-facing text for a rejected push changes deliberately, from the
hardcoded branch-rules guess to the remote's actual response.

## Not in this PR

Deliberately kept out to stay reviewable: `ObservabilityLogger` emits
the stack twice (SLF4J plus `printStackTrace`), and
`GlobalExceptionHandler.getResponseDTOMono` releases the lock using a
bare application id while `GitRedisUtils` stores it under
`application-<id>`, so that defensive release never matches. Both are
filed separately.

## Relationship to the EE PR

EE counterpart: appsmithorg/appsmith-ee#9373

This PR carries the 15 files shared between CE and EE. The EE PR
additionally covers EE-only surfaces with no CE equivalent: package git,
the SSH key service, the continuous-delivery publish path, and EE's
`FileUtilsImpl`.

## Test plan

- [ ] `mvn -pl appsmith-server -am compile` passes (verified locally,
BUILD SUCCESS)
- [ ] Spotless clean (verified locally)
- [ ] Reject a push on a deploy preview with a protected branch on the
remote, and confirm the remote's message appears in the server log and
in the UI error
- [ ] Confirm a successful commit and push emits no new INFO lines
- [ ] Hold a git lock and confirm one warning on retry exhaustion, not
twenty
- [ ] Confirm auto-commit no longer logs "is not allowed" for an
eligible run


## Automation
/ok-to-test tags="@tag.All"

<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30426486864>
> Commit: 67dc29f
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30426486864&attempt=2"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Wed, 29 Jul 2026 14:28:10 UTC
<!-- end of auto-generated comment: Cypress test results  -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Improved Git push status reporting with centralized accepted/rejected
handling and clearer remote rejection diagnostics.
* Fixed remote reference matching during checkout to avoid incorrect
“already exists” results.
* Enhanced push rejection recovery messaging for non-fast-forward and
other remote rejection cases.

* **Reliability**
* Strengthened contextual error logging across git file/repo operations,
including richer path and exception details.
* Improved Redis lock acquisition/release and auto-commit
eligibility/cleanup diagnostics, including outcomes when lock cleanup is
skipped or fails.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
…ies (#42071)

## Description

key Caddy rate limit on trusted client IP, restrict trusted_proxies

> **CE PR.** The EE validation PR listed below already ran the full EE
> suite, Cypress included, and came back green. Merge this CE PR first;
the
> hourly CE→EE sync then carries the fix into EE.

<!-- Smithes will fill from commit messages -->

### Fix

<!-- Smithes will fill from plan — describe the fix, not the
vulnerability -->

### CE/EE sync

<!-- Smithes will fill from check_ce_ee output -->

Merge this PR first. The hourly CE→EE sync propagates it to EE.

The linked EE validation PR is then refreshed from EE `release` and
re-tested.

### EE validation

EE validation PR: appsmithorg/appsmith-ee#9398

EE CI status at the time this PR was opened: **passing**
(ci-test|ci-test-limited, ci-test-result|ci-test-limited-result green).

### Tracking

Linear: https://linear.app/appsmith/issue/APP-15690

> Additional context for reviewers lives in the linked ticket and the
internal
> Slack thread, not in this PR. Please keep it that way in review
comments too.

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30612431000>
> Commit: a1c2c37
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30612431000&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Fri, 31 Jul 2026 08:24:27 UTC
<!-- end of auto-generated comment: Cypress test results  -->

## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No

---------

Co-authored-by: appsmith-smithes[bot] <appsmith-smithes[bot]@users.noreply.github.com>
…ion to the SSRF-validated address (#42060)

## Description

**Problem** (APP-15713 / #42024): SMTP test emails from Admin Settings
fail whenever TLS is enabled — STARTTLS on 587/2525 and implicit SSL on
465 — with:

```
jakarta.mail.MessagingException: Could not convert socket to TLS
javax.net.ssl.SSLHandshakeException: (certificate_unknown) No subject alternative names matching IP address
```

Plaintext SMTP (e.g. 2525 with TLS off) works, which matches the
reporter's port matrix exactly.

**Root cause**: the SSRF fix for GHSA-vvxf-f8q9-86gh (#41666) made
`EnvManagerCEImpl.sendTestEmail` connect to the DNS-resolved IP
(`setHost(resolvedAddress.getHostAddress())`) to close a DNS-rebinding
TOCTOU. But JavaMail performs SNI and certificate identity checking
against the connect host, and server certificates carry hostnames, not
IPs — so every TLS handshake fails.

**Fix**: `buildMailSender` now sets the sender host to the user-entered
hostname (restoring correct SNI + certificate identity checking) while
pinning the TCP connection to the
`RestrictedHostFilter.resolveIfAllowed`-validated address via a custom
`mail.smtp.socketFactory`. Angus Mail asks the factory for an
unconnected socket and connects it to `(host, port)` itself; the pinned
socket ignores the re-resolved endpoint address and connects to the
validated one. Both security properties of the original fix are
preserved:

- **DNS-rebinding TOCTOU stays closed** on the plain/STARTTLS paths
(25/587/2525): the validated address is the one connected to; the
hostname is never re-resolved into something the filter didn't check.
- **Port 465 (implicit SSL) is pinned too**: with no
`mail.smtp.ssl.socketFactory` configured, Angus falls back to the plain
`mail.smtp.socketFactory` for the TCP connect and layers TLS over the
already-connected socket (verified against Angus Mail 2.0.5
`SocketFetcher` bytecode). If that fallback ever stops applying, the
path still fails closed — it is handshake-first with
`mail.smtp.ssl.checkserveridentity` on by default, so a rebound DNS
answer dies at certificate verification before any SMTP dialogue.
- `mail.smtp.socketFactory.fallback=false` is set explicitly so a
factory failure can never silently fall back to an unpinned socket.

The superuser-only authorization, port allowlist, and
`RestrictedHostFilter` validation are unchanged and still run before any
socket is built.

**Tests**: 6 new unit tests in `EnvManagerTest` — hostname-based host
for TLS (fails on the old IP-connecting code), 465 implicit-SSL props,
STARTTLS-disabled props, auth on/off props, and socket-factory pinning
(a factory socket pointed at an unroutable TEST-NET endpoint must land
on the validated listener, for both the unconnected-then-connect path
JavaMail uses and the pre-connected overloads). `mvn test
-Dtest=EnvManagerTest`: 29/29 pass.

**Maintainer note**: the pinning relies on Angus Mail's socket-factory
calling convention (documented in the `buildMailSender` javadoc). When
upgrading the mail library, re-verify that `SocketFetcher` still
consults `mail.smtp.socketFactory` and connects the factory's
unconnected socket itself.

## Manual verification

Verified on a live deploy preview of this PR via Admin Settings → Email
→ "Send test email", against real providers:

| Case | Provider(s) | Result |
|---|---|---|
| 587 + TLS on (STARTTLS) — the reported repro | Mailtrap sandbox, Brevo
| ✅ succeeds, email delivered |
| 465 + TLS on (implicit SSL) | Brevo | ✅ succeeds, email delivered |
| 2525 + TLS off (plaintext, no-regression check) | Mailtrap sandbox | ✅
succeeds |
| Host `169.254.169.254` (SSRF guard) | — | ✅ still rejected with the
generic "Invalid SMTP configuration" (filter fires before any socket is
opened) |

Additionally verified off-DP by driving the real Angus Mail stack
through `buildMailSender` against live `smtp.gmail.com`: the
587-STARTTLS and 465-implicit-SSL handshakes succeed with this fix, and
rebuilding the sender the pre-fix way (host = resolved IP) reproduces
the exact reported failure (`Could not convert socket to TLS`) — same
machine, same server, hostname-vs-IP being the only variable.

Note for anyone re-testing: Mailtrap's sandbox does **not** speak
implicit TLS on port 465 (it greets in plaintext on that port), so 465
must be verified with a provider that does, e.g. Brevo or Gmail. That
failure mode is a provider quirk, not this code path.

Fixes #42024
Linear: https://linear.app/appsmith/issue/APP-15713

## Automation

/ok-to-test tags="@tag.All"

<!-- end of auto-generated comment: Cypress test results  -->

🤖 Generated with [Claude Code](https://claude.com/claude-code)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Bug Fixes**
- Improved SMTP test-email behavior to use the SSRF-validated
destination while keeping the original SMTP hostname for TLS/SNI and
certificate hostname checks.
- Centralized mail-sender configuration (TLS/SSL, StartTLS, auth, and
timeouts) for consistent, correct settings.
- Disabled socket-factory fallback to reduce risk of bypassing address
validation.

- **Tests**
- Added unit tests covering hostname vs resolved IP handling, port 465
SSL behavior, StartTLS-disabled plaintext mode, conditional auth
properties, and pinned socket connections to the validated address.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30640681435>
> Commit: d5301eb
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30640681435&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Fri, 31 Jul 2026 16:05:29 UTC
<!-- end of auto-generated comment: Cypress test results  -->

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
)

/ok-to-test tags="@tag.All"

Linear: https://linear.app/appsmith/issue/APP-15743

## Why

`docker scout cves --only-fixed` on the shipped release image reports
176 fixable vulnerabilities across 70 packages. **52 of them live in
`server.jar` and the plugin jars**, and are controlled from
`app/server/pom.xml`. This clears **40** of those (9 high, 26 medium, 5
low).

This is the direct successor to #41928 (`bump Spring Boot to 3.5.14 and
Netty to 4.1.135`) and #41947 (`batch security update — 17 CVEs from
release image scan`).

## What changed

| Property | From | To |
|---|---|---|
| `spring-boot-starter-parent` | `3.5.14` | `3.5.16` |
| `netty.version` | `4.1.135.Final` | `4.1.136.Final` |
| `jackson-bom.version` | `2.18.8` | `2.18.9` |
| `commons-lang3.version` | *(BOM default 3.17.0)* | `3.18.0` |
| `httpclient` (dependencyManagement) | *(transitive 4.5.9)* | `4.5.14`
|

Two worth explaining:

- **jackson stays on the 2.18.x line.** Spring Boot 3.5.x manages
jackson at 2.21.x; the existing `2.18.8` entry is a deliberate pin
*downward* for CVE-2026-54512 / CVE-2026-54513. Moving to 2.18.9
respects that intent while picking up CVE-2026-59889, CVE-2026-54515 and
GHSA-mhm7-754m-9p8w. It also drags the plugin jars up from 2.16.0.
- **`commons-lang3` needed a property, not a dependency.**
`appsmith-interfaces` already declares 3.18.0 directly, but the Spring
Boot BOM manages it to 3.17.0 and that is what was landing in
`server.jar`.

The unreferenced `jackson.version` property is removed — Spring Boot
imports `jackson-bom.version` only, and `${jackson.version}` is not
expanded anywhere in the repo. Removing it moves no resolved version.

## Verification

`mvn dependency:tree` across `appsmith-server` and the plugin modules
confirms every pin resolves as intended:

```
com.fasterxml.jackson.core:jackson-databind    2.18.9
io.netty:netty-codec-http                      4.1.136.Final
io.netty:netty-common                          4.1.136.Final
org.apache.commons:commons-lang3               3.18.0
org.apache.httpcomponents:httpclient           4.5.14
ch.qos.logback:logback-core                    1.5.34
org.springframework:spring-webflux             6.2.19
org.springframework.security:spring-security-web  6.5.11
com.google.guava:guava                         32.0.1-jre
```

Full reactor compiles clean; `mvn spotless:check` passes. Validated on
the EE side first in appsmith-ee#9405, where the full Cypress suite is
green.

## What is deliberately NOT here

| Finding | Why not |
|---|---|
| `vertx-core` 4.5.21 (2 medium) | Part of a 4.5.21 family; pinning one
artifact risks version skew. Needs the family moved together. |
| `log4j-core` 2.20.0 (3 medium), `nimbus-jose-jwt` 9.37.2 (1 medium) |
Shaded inside a vendor uber-jar — absent from the resolved tree, so no
`dependencyManagement` pin reaches them. Needs a `databricks-sdk-java`
upgrade. |
| `bcpkix-jdk15on` 1.70 (2 medium) | Transitive from `sshj 0.35.0`; the
`jdk15on` line ended at 1.70 and sshj 0.37+ moves to `bcpkix-jdk18on`.
That is the SSH library behind git deploy keys — deserves its own PR. |
| `logback` | Boot 3.5.16 brings 1.5.34, which is already outside the
affected range (`<1.5.34`) for both logback advisories. No pin needed. |

## Known false positives

- **`com.appsmith/server` and `com.appsmith/interfaces`** (3 high) — the
jars are versioned `1.0-SNAPSHOT`, which sorts below the advisories'
`1.99`/`2.0` fixed versions, so they are flagged permanently.
GHSA-j9gf-vw2f-9hrw is already fixed (#41766).
- **`mssql-jdbc` CVE-2025-59250** (1 high) — affected range is
`>=11.2.0.jre11, <11.2.4.jre11` and `mssqlPlugin` declares exactly
`11.2.4.jre11`. Scout normalises the classifier away and compares
`11.2.4 < 11.2.4.jre11`.

<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30653707840>
> Commit: 68f0af9
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30653707840&attempt=2"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Fri, 31 Jul 2026 21:13:48 UTC
<!-- end of auto-generated comment: Cypress test results  -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Maintenance**
* Updated underlying application components and libraries to newer
versions.
* Added dependency management improvements for improved compatibility
and security.
  * No user-facing features or behavior changes were introduced.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
)

## Description

reject MSSQL database name with connection-string separator

<!-- Smithes will fill from commit messages -->

### Fix

<!-- Smithes will fill from plan — describe the fix, not the
vulnerability -->

### CE/EE sync

<!-- Smithes will fill from check_ce_ee output -->

Merge this PR first. The hourly CE→EE sync propagates it to EE.

### EE counterpart

EE PR: appsmithorg/appsmith-ee#9409

EE CI when this PR was opened: **passing** (ci-test|ci-test-limited,
ci-test-result|ci-test-limited-result green).

### Tracking

Linear: https://linear.app/appsmith/issue/APP-15746

> Additional context for reviewers lives in the linked ticket and the
internal
> Slack thread, not in this PR. Please keep it that way in review
comments too.

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30679150865>
> Commit: 3fb8c8b
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30679150865&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Sat, 01 Aug 2026 03:08:17 UTC
<!-- end of auto-generated comment: Cypress test results  -->

## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No

---------

Co-authored-by: appsmith-smithes[bot] <appsmith-smithes[bot]@users.noreply.github.com>
…sed to action run (#42021)

## Description

Filepicker Binary-format data passed alongside other params to
`Api.run()` caused **every sibling param to become `null`** and
`{{this.params}}` to become `null`.

**Reproduce:** Filepicker with Data Format = Binary, then
```js
await Api1.run({ name: "Test", sources: Filepicker1.files })
```
`name` arrives as `null` (and `this.params` is `null`). Base64 format
and the no-file case work fine.

**Root cause:** `DataTreeEvaluator.evaluateActionBindings` serialized
the whole params object into a single `{{
${JSON.stringify(executionParams)} }}` binding and re-parsed it with the
brace-counting `getDynamicStringSegments`. Filepicker Binary data is a
raw `readAsBinaryString` byte string that routinely contains unescaped
`{`/`}` bytes; `JSON.stringify` does not escape braces, so the counter
unbalances and the **entire** params object collapses to `undefined`.
Base64 works because its alphabet has no braces.

**Fix:** `JSON.stringify` emits only literals, so that round-trip could
only deep-clone the (already fully-evaluated) params — it never resolved
nested bindings. Replace it with the already-imported JSON-safe deep
clone `klonaJSON(executionParams)`. This is behavior-preserving for
valid cases, faithfully passes JS values through, avoids re-serializing
multi-MB binary payloads, and removes the brace vulnerability entirely.

**Reviewer notes:**
- Intentional (more-faithful) behavior change now covered by tests:
`undefined`/`NaN`/`Date` param values pass through unnormalized instead
of being JSON-coerced.
- `generateOverrideContext` already receives the raw `executionParams`
object, so its (EE) contract is unchanged.
- Verified red→green: on the old code the regression test returns
all-`undefined` params (the exact bug); on the fix all
`evaluateActionBindings` tests pass.

**TL;DR:** Filepicker Binary data in `Api.run()` params no longer nulls
out the other params — the params object is now deep-cloned instead of
round-tripped through the `{{ }}` binding parser.

Fixes appsmithorg/appsmith-ee#8639

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30824007861>
> Commit: f7bae03
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30824007861&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Mon, 03 Aug 2026 15:45:44 UTC
<!-- end of auto-generated comment: Cypress test results  -->

## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Fixed action parameter evaluation when values contain unbalanced
braces, preserving sibling parameters and correct results.
* Prevented already-evaluated parameters from being altered through
template parsing or type conversion.
* Improved handling of execution parameter references during dynamic
value evaluation.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…pro (#42083)

## Description

authorize caller for target artifact before reading auto-commit progress

<!-- Smithes will fill from commit messages -->

### Fix

<!-- Smithes will fill from plan — describe the fix, not the
vulnerability -->

### CE/EE sync

<!-- Smithes will fill from check_ce_ee output -->

Merge this PR first. The hourly CE→EE sync propagates it to EE.

### EE counterpart

EE PR: appsmithorg/appsmith-ee#9413

EE CI when this PR was opened: **passing** (ci-test|ci-test-limited,
ci-test-result|ci-test-limited-result green).

### Tracking

Linear: https://linear.app/appsmith/issue/APP-15748

> Additional context for reviewers lives in the linked ticket and the
internal
> Slack thread, not in this PR. Please keep it that way in review
comments too.

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30862628683>
> Commit: d3f78d6
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30862628683&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Tue, 04 Aug 2026 00:34:42 UTC
<!-- end of auto-generated comment: Cypress test results  -->

## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No

---------

Co-authored-by: appsmith-smithes[bot] <appsmith-smithes[bot]@users.noreply.github.com>
## Description

**TL;DR** — Ask AI (AI-assisted code editing in the JS/query editors,
plus an admin page to configure the AI provider) currently exists only
in the enterprise edition. Nothing about it is actually
enterprise-specific, so this brings it to CE. The code is ported from
`appsmith-ee/release` unchanged where it already lives in `ce` packages,
and moved from `src/ee` into `src/ce` where it does not.

### Background

Ask AI was originally built for CE on `feat/enable-ai` (PR #41590). That
PR was handed over for review in March, went quiet, and was closed by
the stale bot on 2026-04-03 without ever being merged. The feature
instead shipped in the enterprise repo as `appsmith-ee#8845`, and CE
received only inert stubs via #41692 —
`ce/selectors/aiAssistantSelectors.ts` and friends returning `null` /
`false` / `[]`.

That split was not driven by any technical requirement:

- `ee/selectors/aiAssistantSelectors.ts` contains **no license or
entitlement check** — it reads `state.aiAssistant` and nothing else.
- Enablement is ordinary organization configuration
(`AIAssistantConfig.isAIAssistantEnabled`), set by an instance admin.
- The feature flag that once gated it was removed wholesale in
`appsmith-ee#9119`.

The enterprise-only placement was a product decision, and this PR
reverses it.

### Why port from EE rather than revive the original branch

`feat/enable-ai` is four months stale and EE has since reworked the
implementation:

| | `feat/enable-ai` | `appsmith-ee/release` |
|---|---|---|
| AI settings storage | flat fields on `OrganizationConfiguration` |
nested `AIAssistantConfig` document |
| Provider dispatch | inline `if` chain | extracted `dispatchToProvider`
|
| Datasource schema enrichment | client-side | server-side
`AiDatasourceSchemaSerializerCE` |
| `/ai-config` endpoints | ~1450 lines inlined into
`OrganizationControllerCE` | dedicated `AIConfigControllerCE` +
`AIConfigServiceCE` |
| `AIReferenceServiceCEImpl` | 239 lines | 107 lines |

Reviving the branch would land a divergent second implementation and
guarantee a conflict with the community sync. Porting EE's current
version starts CE and EE byte-identical on the `ce`-package files. Note
the security commit and the review fixes on top of it deliberately move
CE **ahead** of EE, so the sync is no longer a no-op — see **CE→EE sync:
required resolution** below for the exact steps.

### Architecture

**Server** — follows the existing `controller → ce service →
ce_compatible → ee override` layering, all in `ce` packages:

- `AIConfigControllerCE` / `AIConfigController` for `/ai-config`
(`test-connection`, `fetch-models`, `test-api-key`), each gated on
`MANAGE_ORGANIZATION`
- `AIConfigServiceCE(Impl)`, `AIAssistantServiceCE(Impl)`,
`AIReferenceServiceCE(Impl)` with their `ee` override points and
`AIConfigServiceCECompatible(Impl)`
- `AIAssistantConfig` on `OrganizationConfiguration`, `Migration075`,
and the `AIProvider` / DTO types
- `POST /users/ai-assistant/request` on `UserControllerCE`
- `ai-references/*.md` prompt-reference resources

**Client** — the implementation moves from `src/ee` into `src/ce`, which
is where a CE-owned feature belongs. This is safe because the EE UI
files import nothing EE-only; every import is a package, a shared path,
or an `ee/` alias that resolves through CE's shims. The existing
`src/ee` shims from #41692 are untouched and now re-export real code
instead of stubs, and the exported symbol surface of every relocated
file is unchanged. The AI reducer and saga are registered in
`ce/reducers` and `ce/sagas` rather than their `ee` counterparts, and
the admin AI settings page is registered for superusers.

**This PR adds no `src/ee` files**, because the CE pre-push architecture
guard rejects them. Four CE-owned modules therefore have no `ee` shim to
import through — `aiAssistantReducer`, `AIAssistantSagas`, `GPT/shared`,
and the admin AI config — so they are imported from `ce/` directly, each
with a documented `eslint-disable` for `no-restricted-imports`. That is
the same accommodation the native Custom Widget copilot uses in #42063.
If EE would rather route these through `ee/` shims, those shims belong
in a companion EE PR.

Adds `react-markdown` and `remark-gfm`, used by the assistant's response
renderer.

### Impact on existing instances

Inert by default. `AIAssistantConfig` is absent until an admin
configures a provider, `isAIAssistantEnabled` defaults to false, and
`Migration075` only adds the field. With nothing configured, the Ask AI
affordances stay hidden exactly as they do today — no feature flag is
involved, matching how EE ships it since #9119.

### Security fixes included

A nine-reviewer council on the ported code surfaced four defects. All
four are inherited byte-identical from EE and are therefore **live in EE
production today**; because EE's `AIConfigServiceImpl` delegates every
method to the CE class and `AIAssistantServiceImpl` overrides nothing,
fixing them here carries them into EE through the sync rather than
needing a parallel EE change.

1. **SSRF, two call sites.** `callLocalLLMAPI` built a raw `WebClient`,
bypassing `WebClientUtils` and substituting a check that tested only
`isLinkLocalAddress` on the first resolved address — missing loopback,
and racy. `callAzureOpenAIAPI` chained `.clientConnector(...)` *after*
`WebClientUtils.builder()`, which replaces the connector carrying the
DNS-aware resolver; it read as protected and was not. Both now build
through `WebClientUtils.builder(httpClient)`.
2. **`getAIConfig` authorization.** It was the only one of five service
methods without `MANAGE_ORGANIZATION`, disclosing `localLlmUrl`,
`azureOpenaiEndpoint` and the deployment name to any authenticated user,
on every session. Managers still get the full configuration; everyone
else gets enablement, provider, and credential-presence booleans —
exactly what the client consumes.
3. **API keys stored in cleartext.** The `@Encrypted` annotations never
applied — the traversal only descends into `AppsmithDomain` types, and
the write is a sparse `updateById` so the encrypting lifecycle listener
never fires. `AIConfigSecretsCE` now encrypts and decrypts at the few
write/read points, and `Migration076` encrypts existing values in place,
idempotently.
4. **Admin key field corrupted credentials.** A stored key loaded into
the input as the literal `••••••••` with a save guard comparing against
that mask, so typing without clearing persisted `••••••••sk-…` behind a
success toast.

**Behaviour change worth calling out:** a local-LLM URL pointing at
loopback is now refused. In the single-container CE deployment
`127.0.0.1` is Mongo, Redis and RTS rather than the operator's Ollama —
which is the reason to refuse it. A local model on another host or
container stays reachable by hostname or private IP. This also makes the
runtime path agree with `/ai-config/test-connection`, which already went
through `WebClientUtils`.

### Follow-ups (tracked, not addressed here)

1. **Unmetered LLM spend** — `/users/ai-assistant/request` has no rate
limit or per-user quota; on an open-signup CE instance any account can
drain the admin's provider billing.
2. **OpenAI provider lacks guards the others have** — no
empty/max-length prompt validation and no `max_tokens`.
3. **`/users/ai-assistant/request` maps every failure to 400**,
including upstream timeouts, which hurts monitoring.
4. **A measured 0.5–1.0 s reactive-thread stall** in
`AiDatasourceSchemaSerializerCE.extractReferencedTableNames` at the
DTO's own size ceilings.
5. **Dead code carried from EE** — `AIWindow` and the in-editor
`AISidePanel` have no importer, and `ce/utils/aiSchemaSerializer.ts` has
no consumer but its own test.
6. **Test coverage** — `AIConfigSecretsCE` and `Migration076` both route
through `EncryptionHelper`, whose static initialiser needs
`APPSMITH_ENCRYPTION_PASSWORD`/`SALT`. Those are set for the
integration-test and Docker CI jobs but not for `server-unit-tests`, so
this coverage belongs in the integration suite.

A follow-up in `appsmith-ee` should reduce EE's `src/ee` Ask AI files to
re-export shims and drop its `ee/reducers` + `ee/sagas` registration, so
EE consumes this CE implementation instead of shadowing it.

https://linear.app/appsmith/issue/APP-15737

Supersedes the original, stale-closed CE attempt in #41590.

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30836147916>
> Commit: deab697
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30836147916&attempt=2"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Mon, 03 Aug 2026 18:47:45 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [x] Yes
- [ ] No

Ask AI becoming available in the community edition is a user-facing
change worth announcing.



## CE→EE sync: required resolution

**This section is load-bearing. The sync of this PR is not a no-op, and
two of its failure modes arrive through *clean* merges — no conflict
marker will surface them.** Whoever runs the sync should follow this,
and it is the condition the architecture review set for unblocking.

Of the changed files that also exist in EE, **18 differ from EE's
copy**. Most are the deliberate hardening in the security commit, which
moves CE ahead of EE on purpose. Five are add/add conflicts
(`ce/sagas/AIAssistantSagas.ts`, `ce/pages/AdminSettings/config/ai.tsx`,
`pages/AdminSettings/AI/index.tsx`, `AIAssistantServiceCEImpl.java`,
`AIConfigServiceCEImpl.java`).

> **These steps are for the sync itself. None of them can be pre-landed
in EE as a separate PR — verified against `appsmith-ee/origin/release`
(`0aff44fa56`, "Sync community release"):**
>
> - **The saga.** EE's `ce/sagas/index.tsx` does **not** register the AI
saga yet — only `ee/sagas/index.tsx` does. Removing EE's registration
*before* the CE change syncs would leave zero registrations and take Ask
AI out of EE entirely. It is only safe once CE's registration has
arrived.
> - **The enum.** EE's `ASK_AI_ORG_CONFIG_UPDATED` /
`ASK_AI_ORG_TEST_RUN` are referenced by `AIConfigServiceCEImpl` (lines
172-173, 236) and its test. Deleting them ahead of the sync breaks EE's
compile. This is a conflict *resolution*, not a change that exists
independently.
>
> So this is work for whoever runs the sync, in the same merge — not a
companion PR that can land first.

### 1. Remove EE's now-duplicate saga registration

CE now registers the AI saga itself, and that CE file merges **cleanly**
into EE — so EE ends up registering it twice:

| EE file | What to do |
|---|---|
| `app/client/src/ee/sagas/index.tsx` | **Remove** the
`aiAssistantSagas` import (from `ee/sagas/AIAssistantSagas`, a shim that
re-exports `ce/sagas/AIAssistantSagas`) and its entry in the saga array
— CE's registration now covers EE |

Left as-is, EE runs the *same* watcher generator twice, so every Ask AI
action fires duplicate requests to the provider — double latency and
double spend.

This one genuinely needs an EE change: EE builds `sagasArr` as
`[...CE_Sagas, …, aiAssistantSagas]`, appending its own entry *after*
spreading CE's list, so CE cannot deduplicate it from its side.

**The duplicate admin category no longer needs an EE change.**
`ConfigFactory.register` is CE-owned and was a raw push into three
collections (`categories`, `settings`, `savableCategories` — only
`settingsMap` was keyed and therefore safe). It is now idempotent, so a
category registered from both `ce/` and `ee/` collapses to one entry on
its own. EE's `ConfigFactory.register(AIConfig)` can stay exactly as it
is.

### 2. Resolve the five add/add conflicts toward CE, wholesale

`Migration076EncryptAIAssistantApiKeys` merges cleanly and will encrypt
EE's stored keys on first boot. EE's current `AIAssistantServiceCEImpl`
/ `AIConfigServiceCEImpl` read those keys **without**
`AIConfigSecretsCE.decrypt`. If either file is resolved toward EE's
copy, **EE sends ciphertext as its `Authorization` header and Ask AI
breaks in EE**.

`pages/AdminSettings/AI/index.tsx` must also move together with
`AIConfigServiceCEImpl` — the client's `hasStoredX` model depends on the
server's `has*` response shape and the manager-only full config.

### 3. Collapse the duplicated analytics enum

`AnalyticsEvents.java`: CE adds `ASK_AI_ORG_CONFIG_UPDATED` /
`ASK_AI_ORG_TEST_RUN` at the enum tail (lines 106/109); EE already has
both at lines 140/143. Naive resolution produces duplicate enum
constants and **fails to compile**. Keep one pair.

### Correction to an earlier claim in this description

An earlier revision said porting from EE keeps the two editions
"byte-identical on the `ce`-package files, so the sync stays a no-op".
That was true of the initial port and is **no longer true**: the
security commit, and the review fixes on top of it, deliberately move CE
ahead. The byte-identity argument still holds for the ~40 untouched
ported files and for the reason to port rather than revive
`feat/enable-ai`, but the sync itself needs the three steps above.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added Ask AI assistance for JavaScript, SQL, GraphQL, and JSON
editing.
* Added resizable chat panels with conversation history, editor context,
Markdown responses, quick actions, and keyboard shortcuts.
* Added a global AI assistant panel with context-aware prompts and
schema support.
* Added administrator settings for Claude, OpenAI, Azure OpenAI, and
local Ollama-compatible providers.
* Added connection, credential, and model testing with secure credential
handling and request safeguards.
* **Documentation**
* Added reference guides for JavaScript, SQL, GraphQL, and common
troubleshooting scenarios.
* **Tests**
  * Added coverage for schema handling and AI configuration workflows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
)

## Description

Removes the Redis pub/sub plugin-install pipeline and the remote JAR
download/hot-load mechanism
(`PluginServiceCEImpl.downloadAndStartPlugin`, `redisInstallPlugin`,
`RedisListenerConfig`, `InstallPluginRedisDTO`), plus the now-unused
`APPSMITH_REMOTE_API_KEY` dummy env var in the ci-test workflows.

This path dates from the 2019 single-server model: it wrote to ephemeral
container disk (`../dist/plugins/`), had no startup reconciliation, and
relied on non-durable Redis pub/sub fan-out, so it cannot work in a
multi-pod deployment. Nothing sets `jarLocation` anymore, so the
download block was unreachable in practice.

Not affected:
- Bundled plugin loading at container startup via PF4J (separate path,
untouched)
- Workspace plugin association (`installPlugin`) — still works, now
writes the association directly instead of also publishing a no-op Redis
event
- The scheduled remote-plugin metadata sync

Also removes the rest of the now-dead `appsmith:queue` channel: the
unused `ReactiveRedisTemplate`/`ChannelTopic` constructor parameters on
the plugin service, the `/redisPub` debug endpoint (it could only report
zero subscribers with the listener gone), and the `ChannelTopic` bean.

Linear: https://linear.app/appsmith/issue/APP-15381

## Automation

/ok-to-test tags="@tag.All"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30563536670>
> Commit: 49257c4
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30563536670&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Thu, 30 Jul 2026 18:04:17 UTC
<!-- end of auto-generated comment: Cypress test results  -->



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Plugin installation now records workspace plugin information directly,
improving installation reliability.
* Runtime hostnames are recognized by SSRF protection for improved
connectivity in deployed environments.

* **Bug Fixes**
  * Removed legacy Redis-based plugin installation and testing pathways.
* Simplified plugin and application startup by eliminating unused Redis
listener configuration.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…42026)

## Description

**TL;DR:** Adds a new **Card widget** — a container that displays a
single logical entity (customer, order, product, task…) with prop-driven
chrome (media slot, header with title/subtitle/avatar/badge/overflow
menu, footer action buttons) wrapped around a fully composable body
canvas where any Appsmith widgets can be dropped. Built for dashboards,
CRMs, catalogs, and admin panels; works standalone and inside List v2
with `{{currentItem}}` bindings.

### What's included

- **Four zones:** media (top cover / left thumbnail / none, with
broken-image fallback), header (avatar or icon, title, subtitle,
color-coded status badge, ⋮ overflow menu), body (a real child canvas —
embed any widgets), footer (configurable action buttons, themed like
Button Group).
- **Data binding:** every chrome prop is bindable; a `cardData` object
property serves as a convenience binding target and is seeded by
query-editor bind-to-widget (sniping mode).
- **States & events:** `isSelected` / `isExpanded` meta properties with
`defaultSelected` / `defaultExpanded`, `onSelect` / `onExpand` /
`onCollapse` / `onCardClick` events, disabled state, loading skeleton,
hover elevation, clickable-card mode with keyboard activation;
`setSelected` / `setExpanded` / `setDisabled` / `setVisibility` setters
for JS access.
- **Layout:** fixed and auto-layout support, dynamic height,
collapse-to-header; inside List v2 rows the card renders per-row with
row-scoped state and events (auto-height dispatches are guarded off for
meta widgets by platform design).
- **Accessibility:** semantic `<article>`, `role="button"`/Enter/Space
when clickable, `aria-pressed` / `aria-expanded` / `aria-disabled`,
labeled icon-only controls.
- **Theming:** border radius, box shadow, and accent colors inherit the
app theme via the stylesheet config.

### Platform fix included: duplicated "Height" control in the property
pane

> [!IMPORTANT]
> **This is not a Card-only fix.** It repairs a defect that already
ships today on JSON Form and six WDS widgets.

`enhancePropertyPaneConfig` injected the `dynamicHeight` ("Height")
control by pushing into the widget's *own* config object. Widgets whose
`getPropertyPaneContentConfig()` returns a module-level array hand back
the same section object on every call, so the control accumulated on
each rebuild — and rebuilds happen more than once per session, because
`clearAllWidgetFactoryCache()` drops the memoized configs (from
`InitSagas`, from `EvaluationsSaga` on `WIDGET_INIT_SUCCESS`, and now
from `loadAndRegisterOnlyCanvasWidgets` on every lazy registration). The
result was a **Height dropdown rendered twice, with its helper text
repeated**.

**Affected widget types**, confirmed by enumerating all registered
widgets against the pre-fix implementation:

| Widget type | Shipped today? |
|---|---|
| `JSON_FORM_WIDGET` | ✅ yes — users can hit this now |
| `WDS_CHECKBOX_WIDGET` | ✅ yes |
| `WDS_CHECKBOX_GROUP_WIDGET` | ✅ yes |
| `WDS_SWITCH_WIDGET` | ✅ yes |
| `WDS_SWITCH_GROUP_WIDGET` | ✅ yes |
| `WDS_RADIO_GROUP_WIDGET` | ✅ yes |
| `WDS_PARAGRAPH_WIDGET` | ✅ yes |
| `CARD_WIDGET` | new in this PR |

Notes for reviewers:
- **No data migration or backfill is needed.** Property pane config
never reaches the DSL, and both duplicate controls shared one
`propertyName` and one pure `updateHook`, so no saved app was corrupted.
- **This fix is a prerequisite for the rest of the PR, not an optional
extra.** The auto-height registration guard on this branch calls
`clearAllWidgetFactoryCache()` on every lazy registration, which makes
the duplication fire *more* often. It is committed first for that
reason.
- **EE needs no lockstep change** — `WidgetProvider/factory/helpers.ts`
is byte-identical across CE and EE, so the normal sync carries it.

### Card height behaviour

Collapsing a Card behaved differently in the editor and in
preview/published, and in preview it destroyed the card:
`componentDidUpdate` requested a height of `0`, which is the platform's
"widget went invisible" signal rather than "shrink to chrome". In the
editor the update was dropped entirely (card kept its expanded height
with an empty region); in preview/published it forced the minimum to `0`
and collapsed the card to **zero rows — header and expand chevron
included, with no way to re-expand**. The chrome model was also encoded
twice with predicates that had drifted (a bound `mediaHeight` produced a
`NaN` offset, a bound `mediaPosition` under-reserved 140px, `showHeader:
undefined` over-allocated the body by 50px, and a collapsed card still
reserved footer chrome).

Both callers now share one pure helper with numeric coercion and
predicates aligned to what actually renders; the body canvas is clamped
at zero; `minDynamicHeight` reflects the card's chrome (following the
`TabsWidget` precedent); and the properties that change chrome height
now trigger a recompute.

### Design doc

`docs/plans/2026-07-21-card-widget-design.md` (included in this PR) —
architecture decision record (hybrid chrome + canvas body), property
reference, risks, and phased plan.

### Tests

- 21 Jest component tests
(`app/client/src/widgets/CardWidget/component/index.test.tsx`) — zones,
toggles, selection, expand/collapse, disabled, skeleton, keyboard.
- 34 chrome-height parity tests (`CardWidget/chromeHeight.test.ts`) —
asserts the saga's row offset and the renderer's pixel height agree
across the header × footer × media × collapsed matrix, including every
unevaluated-binding case that previously produced `NaN`.
- 8 widget-level tests (`CardWidget/widget/index.test.tsx`) — collapse
requests the real chrome height (never `0`), expand recomputes,
meta-widget / non-fixed-layout / fixed-height guards, and a disabled
card fires no actions.
- 7 property-pane tests
(`WidgetProvider/factory/__tests__/featurePropertyPaneEnhancement.test.ts`)
— the enhancer is non-mutating and yields exactly one control across
repeated rebuilds; every registered widget builds its expected control
count across cache clears, with `CARD_WIDGET` and `JSON_FORM_WIDGET`
named explicitly and pinned to the "General" section.
- `autoHeightSagas/registrationGuard.test.ts` extended — both sagas
continue when widget registration fails, instead of restart-looping
their watcher.
- 2 Cypress specs: `Widgets/Card/Card1_spec.ts` (canvas: zones, property
pane, events, selection, collapse) and `Widgets/Card/Card2_List_spec.ts`
(card inside List v2 with `{{currentItem}}` bindings, per-row rendering)
plus fixture `Listv2/simpleListWithCard.json`.

Verified against a local instance: the property pane shows a single
Height control after a full reload, and collapse reflows 190px → 150px →
190px in the editor and in preview, with the header and chevron intact.

Fixes #17967

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30943346319>
> Commit: c3beebf
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30943346319&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Tue, 04 Aug 2026 20:31:51 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [x] Yes
- [ ] No

Release note should cover two items: the new Card widget, and the
duplicate Height control fix — naming JSON Form and the WDS widgets,
since those shipped the defect to existing instances.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01VsMsupbF5aLfhDXLM7hwZU


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Introduced the Card widget with configurable media, headers, badges,
overflow menus, footer actions, styling, loading states, and child
content areas.
* Added clickable, disabled, selectable, expandable, and collapsible
behaviors with keyboard support and improved accessibility.
  * Added data binding support, including Cards rendered within List v2.
* Added Card support to the widget catalog, help search, auto-layout,
and suggested widget additions.
* **Bug Fixes**
  * Improved auto-height calculations for canvas-based content.
* **Documentation**
  * Added a Card widget design specification.
* **Tests**
  * Added comprehensive unit and end-to-end regression coverage.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
## Summary
Batch security update via resolutions/version bumps.

### Resolved alerts
- Resolves #713, #708 — postcss -> ^8.5.23 (direct dependency, version
bump + resolutions pin)
- Resolves #717, #716, #715 — undici -> ^6.28.0
(transitive/inconclusive, resolutions pin)
- Resolves #714 — fast-uri -> ^3.1.5 (transitive/inconclusive,
resolutions pin)
- Resolves #712, #710 — brace-expansion -> ^1.1.18
(transitive/inconclusive, resolutions pin)

### Skipped (not addressed in this PR)
- #711 — ip-address: current resolved version is 9.0.5 (major 9),
patched version 10.3.1 requires a major bump — skipped per policy (major
bump).
- #703 — @opentelemetry/propagator-jaeger: current 1.27.0, patched 2.9.0
requires a major bump — skipped per policy (major bump).
- #654 — @opentelemetry/core: current pinned ^1.30.0 (resolved 1.30.1),
patched 2.8.0 requires a major bump — skipped per policy (major bump).

No code changes — version bumps and resolutions only in
app/client/package.json (yarn.lock regenerated via yarn install).

/ok-to-test tags="@tag.All"

<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30990746298>
> Commit: 5007f04
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30990746298&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Wed, 05 Aug 2026 09:56:46 UTC
<!-- end of auto-generated comment: Cypress test results  -->

Co-authored-by: appsmith-smithes[bot] <appsmith-smithes[bot]@users.noreply.github.com>
…42090)

## Description

Require edit permission for edit-mode application theme reads

Application theme reads made while in edit mode now check for edit
permission on the application, matching the permission level already
required for other edit-mode operations.

### Fix

The edit-mode theme lookup now verifies edit permission on the
application before returning the theme, instead of accepting the (lower)
permission previously used for that check.

### CE/EE sync

ce-only-safe — the affected code is identical between CE and EE.

Merge this PR first. The hourly CE→EE sync propagates it to EE.

### EE counterpart

EE PR: appsmithorg/appsmith-ee#9426

EE CI when this PR was opened: **passing** (ci-test|ci-test-limited,
ci-test-result|ci-test-limited-result green).

### Tracking

Linear: https://linear.app/appsmith/issue/APP-15750

> Additional context for reviewers lives in the linked ticket and the
internal Slack thread, not in this PR. Please keep it that way in review
comments too.

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30990573873>
> Commit: 97292e2
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30990573873&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Wed, 05 Aug 2026 09:52:02 UTC
<!-- end of auto-generated comment: Cypress test results  -->

## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No

---------

Co-authored-by: appsmith-smithes[bot] <appsmith-smithes[bot]@users.noreply.github.com>
…hooks (#42069)

## Description

`getConsolidatedDataApi` in `cypress/support/Objects/FeatureFlags.ts`
rewrites the `/api/v1/consolidated-api/*` response to inject feature
flags. Its `catch` calls `cy.log`:

```ts
req.reply((res: any) => {
  if (res.statusCode === 200 || res.statusCode === 401 || res.statusCode === 500) {
    try {
      const updatedResponse = JSON.parse(JSON.stringify(res?.body));
      updatedResponse.data.featureFlags.data = ...;
      return res.send(updatedResponse);
    } catch (e) {
      cy.log(`Featureflags.ts error `, e);   // <- inside the intercept handler
    }
  }
});
```

A `cy.intercept` response handler runs outside the Cypress command
queue. Enqueuing a command from there produces:

```
CypressError: The following error originated from your test code, not from Cypress.
It was caused by an unhandled promise rejection.

  > Cypress detected that you returned a promise from a command while also invoking
    one or more cy commands in that promise.

The command that returned the promise was:   > `cy.reload()`
The cy command you invoked inside the promise was:   > `cy.log()`
```

Cypress fails the current test on an uncaught error, so a logging line
in an error path takes down whatever command was in flight when the
intercept resolved.

The `catch` fires when the response body is not the expected shape — the
handler admits `401` and `500` as well as `200`, and those bodies have
no `data.featureFlags`, so `updatedResponse.data.featureFlags.data =
...` throws `TypeError`. That is why this is intermittent: an occasional
non-200 on `consolidated-api` turns into a suite-killing `CypressError`
instead of a log line.

## Evidence

Mined the last 12 scheduled `test-build-docker-image` runs on the EE
mirror (11 had ci-test logs). The signature appears in **7 of 11 runs**,
18 occurrences, across 6 distinct shards.

The inner command is `cy.log()` in **every** occurrence, and
`FeatureFlags.ts:75` is the only `cy.log` inside a `cy.intercept` route
handler anywhere under `cypress/support/` — the other matches are all
inside `.then()` callbacks, where `cy.*` is legal. The outer command
varies with whatever was in flight (`cy.reload()`, `cy.visit()`,
`cy.get()`), which is consistent with the intercept firing during
navigation.

Three of the occurrences landed in a `before all` hook and skipped an
entire suite:

```
Because this error occurred during a `before all` hook we are skipping the
remaining tests in the current suite: `Tests general functionality...`
```

That is `EE/Enterprise/MultipleEnv/ME_CustomEnv_spec.ts`
(`describe("Tests general functionality of custom environment")`), which
is currently the joint-worst repeat offender in the mining table — 3
retry events across 3 runs, on runs 30259133481, 30350063215 and
30507869945, all on shard 2. The remaining occurrences failed a single
test rather than a whole suite.

## Change

One line: log outside the command queue instead of inside it. No
behavior change on the success path, and the `catch` still swallows the
error exactly as before — the response falls through unmodified, as it
does today.

Test support code only. No product code, no spec files, no CI config.

## Verification note

There is no red-before/green-after repro for this. Triggering the
`catch` requires `consolidated-api` to return a body without
`data.featureFlags` — an intermittent backend condition the test cannot
summon on demand. A green Cypress run demonstrates the change does not
break anything; the argument that it removes the failure is the source
above, plus the fact that a `console.log` cannot raise `CypressError`.

Running with `@tag.All` because this file is shared support code loaded
by every spec that intercepts feature flags.

## Automation

/ok-to-test tags="@tag.All"

Tracking: https://linear.app/appsmith/issue/APP-15705


<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30549711772>
> Commit: a7bd558
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30549711772&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Thu, 30 Jul 2026 15:17:14 UTC
<!-- end of auto-generated comment: Cypress test results  -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Tests**
* Improved error handling for API response interception in automated
tests.
* Added diagnostic logging when response processing cannot be completed.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Description

`Regression/Apps/CommunityIssues_Spec.ts` tests 8-10 create, update and
delete a row in the AForce Postgres datasource. That datasource is
shared by every run of this spec, and the row title was a fixed string,
so the rows collide across runs.

When a run fails after test 8, its row survives. On the next attempt
test 8 creates a second row with the same title, and
`table.SearchTable("Suggestion")` matches both of them - the leftover
row's title still contains "Suggestion" even after test 9 changed its
type to Troubleshooting. Test 9 then reads row 0 and updates whichever
row sorts first.

That is visible in the failure output. From release run 30085427662
(shard 1):

```
AssertionError: expected 'Adding Title Suggestion via script-updating title-updating title'
  to equal 'Adding Title Suggestion via script-updating title'
AssertionError: expected 'Suggestion' to equal 'Troubleshooting'
AssertionError: expected 'Troubleshooting' to equal 'Suggestion'
```

The spec appends `-updating title` exactly once per run, so a doubled
suffix can only come from test 9 updating a row that a previous run had
already updated.

This also explains why the spec fails *persistently* rather than
recovering: the leftover row is still there on the retry, so every
attempt inside the job fails the same way. In the last mining window
CommunityIssues was 2/2 persistent (zero recoveries).

## Change

Generate the issue title per run and search for it, so the table filter
matches only the row this run created:

- `issueTitle` is built once per run with a timestamp suffix.
- Test 8 types that title and searches for it instead of the generic
`"Suggestion"`.
- Test 9 asserts against `${issueTitle}-updating title`.

Test 10 is unchanged, and it gets stronger as a side effect:
`WaitForTableEmpty` now runs against a filter that only ever matched
this run's row, instead of one that could still match leftovers from
earlier runs.

One spec file, no product code, no shared support code.

## Verification note

There is no red-before repro for this. Reproducing it requires the
shared AForce table to already hold a leftover row, which is exactly the
state the change prevents. The evidence is the doubled-suffix string
above, which the spec's own code cannot produce in a single run. A green
Cypress run here demonstrates the change does not break the spec; it
does not by itself demonstrate the collision is gone.

## Automation

/ok-to-test tags="@tag.Widget"

Tracking: https://linear.app/appsmith/issue/APP-15705


<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/30358510792>
> Commit: 5bf801d
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30358510792&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.Widget`
> Spec:
> <hr>Tue, 28 Jul 2026 13:29:13 UTC
<!-- end of auto-generated comment: Cypress test results  -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Tests**
* Improved Community Issues regression coverage by generating unique
issue titles for each test run.
* Updated creation, search, and edit validations to consistently use the
generated titles.
* Reduced the risk of test conflicts and false failures caused by reused
issue names.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary

- add a CE-owned native Custom Widget Copilot backed by the CE Ask AI
runtime
- keep the complete component, parser, context contract, configuration
fallback, and tests in `src/ce`
- remove the legacy `internal.appsmith.com` iframe integration now that
Ask AI configuration and execution are CE-owned
- apply complete or partial HTML, Style, and JavaScript responses
directly to the Custom Widget editors
- keep assistant rendering self-contained without introducing new
package dependencies or EE-owned files

## Architecture and community sync

- this PR contains no `src/ee` changes; the CE pre-push architecture
guard passes
- the Custom Widget editor imports the CE implementation intentionally
so EE consumes the same code after community sync, without a shadow
implementation
- both standalone CE and EE use the native assistant; configured
instances get the conversational editor, while unconfigured instances
get administrator guidance

## Impact on existing instances

The AI tab remains behind the pre-existing
`release_custom_widget_ai_builder` flag. When enabled, the tab now
always renders the native assistant in both CE and EE. Instances with a
configured and enabled Ask AI provider get the conversational editor
experience; unconfigured instances get administrator guidance. The
Custom Widget builder no longer loads or communicates with
`internal.appsmith.com`.

## Validation

- `yarn jest src/ce/pages/Editor/CustomWidgetBuilder/Editor/AIAssistant
--runInBand` — 21 tests passed
- focused ESLint — passed with no warnings or errors
- `yarn tsc --noEmit` — passed
- `git diff --check` — passed
- CE pre-commit ESLint and gitleaks hooks — passed
- CE pre-push architecture guard — passed
- prior real-browser validation covered full generation, partial
Style-only changes, multi-turn pivots, Q&A without mutations, error
recovery, persistence, and working previews

## Linear issue

https://linear.app/appsmith/issue/APP-15735

## Automation

/ok-to-test tags="@tag.All"

<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/31007662363>
> Commit: 697e3a8
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=31007662363&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Wed, 05 Aug 2026 13:53:28 UTC
<!-- end of auto-generated comment: Cypress test results  -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a Custom Widget Builder AI Assistant with prompt suggestions,
chat actions, loading and error states, and previews of applied updates.
* Added guidance for unconfigured assistants, including an AI settings
link for administrators.
* Supports applying AI-generated HTML, CSS, and JavaScript updates
directly to widgets.
* **Tests**
* Added comprehensive coverage for assistant interactions, code parsing,
update application, and error handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: subrata71 <subrata@appsmith.com>
## Description

CodeRabbit reviewed
[appsmith-ee#9417](appsmithorg/appsmith-ee#9417)
roughly 30 seconds after its dependency merged, so it saw the stale
39-file diff that still contained the whole Ask AI CE sync from #42065.
All 15 findings landed on CE-owned client and server code that is
already on `release` — none touch the EE shim cleanup that PR actually
makes. They are fixed here, in the repo that owns the code.
`appsmith-ee#9417` is unaffected and stays a 10-file EE-only cleanup.

The EE repo's own pre-commit hook (`check-ee-only-files.sh`)
independently confirms the split: it refuses any client change outside
`src/ee/`.

### Critical — a saved credential could be sent to a caller-chosen host

`AIConfigServiceCEImpl.testApiKeyInternal` decrypted the stored provider
key when the request omitted one, then sent it to the `baseUrl` /
`endpoint` supplied in that same request. Since the UI masks these keys
as `••••••••`, an organization admin could read one back by pointing the
test at a collector they control. No transport requirement existed
either, so the key could leave over plain HTTP.

The endpoint is gated on `MANAGE_ORGANIZATION`, so this is admin-only
rather than unauthenticated — but it still recovers a secret the product
deliberately hides.

The saved configuration now decides the destination whenever the key
comes from storage. Only fields that cannot change the host — deployment
name, API version, model — remain overridable, so an administrator can
still test a different deployment against their own resource. A stored
credential is no longer sent anywhere that would put it on the wire in
cleartext; loopback stays exempt, and typing a key into the form still
tests any endpoint explicitly.

### Major

- **Encrypted credentials now carry a marker.** `AIConfigSecretsCE`
inferred "is this encrypted?" by attempting a decrypt, which answers the
wrong question in both directions. After the instance encryption
password changes, real ciphertext stops decrypting — it was reported as
cleartext, handed to the provider as the API key, and re-encrypted by
the next write, at which point the original was unrecoverable.
Conversely, cleartext that happened to decrypt was treated as encrypted
and never protected. A marked value that will not decrypt now raises
instead of yielding its own ciphertext.
- **`Migration076` normalises pre-marker values.** Cleartext is
encrypted; ciphertext written by a build that encrypted without marking
keeps its bytes and simply gains the marker, so it is never encrypted
twice. The change unit is edited in place rather than stacked because it
is in no release tag and has therefore never run.
- **Ask AI failures report a real HTTP status.** Everything was
rewritten to `INVALID_PARAMETER`, so a provider outage, an invalid key
and a throttled caller all returned 400 — outages stayed out of
server-error metrics, and clients could not tell "back off" from "bad
request". Errors keep their own class now, unexpected ones are chained
as the cause, and throttling (ours and the provider's) returns 429.
- **Submissions are serialised.** The editor panel dispatched
independently from the send button and each quick-action chip, with the
chips live during a request, so two clicks meant duplicate chat entries
and a second billable provider call.

### Minor

Resize listeners no longer survive an unmount mid-drag in either panel;
Escape closes the global panel wherever focus sits, matching its own
"Close (Esc)" tooltip; Clear Chat is disabled during a request; the
context label follows the caret instead of showing the line the panel
opened on; `graphql-js` is recognised by `isAISupportedMode`, so Ask AI
works in GraphQL editors; the config update path maps
`NO_RESOURCE_FOUND` to an authorization refusal rather than a 404; and
the Azure error body is no longer logged a second time uncapped.

## Verification

- 21 server unit tests pass, 12 of them new: `AIConfigSecretsCETest` (9)
pins the marker, the round trip, migration normalisation, and the loud
failure on a changed encryption password; `AIConfigServiceCEImplTest` (3
new) pins destination selection by giving the request an HTTPS host and
the saved config an HTTP one, so the refusal proves the saved value won.
- `tsc --noEmit` reports no errors in any changed file (only the
pre-existing `packages/ast` and `packages/design-system` failures that
are on `release` too).
- ESLint: 0 errors on all four changed client files. Prettier and
Spotless clean.

Linear: https://linear.app/appsmith/issue/APP-15756

Slack thread:
https://theappsmith.slack.com/archives/C09NG5BJ18S/p1785930741904329

## Automation

/ok-to-test tags="@tag.All"

## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No

<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/31047449928>
> Commit: 2adc822
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=31047449928&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Wed, 05 Aug 2026 22:13:45 UTC
<!-- end of auto-generated comment: Cypress test results  -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * AI context now shows the current editor line.
  * Stored AI provider keys can be tested without re-entering them.
  * GraphQL editor support is more consistent.
  * Destination changes warn when stored credentials will be removed.

* **Bug Fixes**
* AI submissions and chat clearing are disabled while requests process.
  * Improved AI error messages and rate-limit handling.
  * Prevented credentials from being sent to unsafe destinations.
  * Improved panel keyboard shortcuts and drag behavior.
  * Strengthened encryption handling for stored AI credentials.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary

- render Custom Widget AI assistant responses with the existing shared
Ask AI Markdown renderer while keeping user messages as plain text
- expose the existing CE Markdown renderer through the edition-aware GPT
barrel so CE and EE reuse one implementation
- animate the Generating loader icon
- add regression coverage for the assistant/user rendering boundary

## Testing

- CE: 29 Custom Widget AI Assistant tests pass
- CE: ESLint passes with no new errors
- CE: TypeScript check passes
- EE sync simulation: final net patch applies cleanly onto latest
appsmith-ee release
- EE sync simulation: no PR-related TypeScript failures
- git diff validation and CE pre-push edition guard pass

## Linear


https://linear.app/appsmith/issue/APP-15735/replace-internal-appsmith-app-with-native-co-pilot-component

## Automation

/ok-to-test tags="@tag.All"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/31082751527>
> Commit: 61a8087
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=31082751527&attempt=2"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Thu, 06 Aug 2026 09:11:50 UTC
<!-- end of auto-generated comment: Cypress test results  -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * AI assistant responses now support formatted Markdown rendering.
* User messages continue to display as plain text for clear distinction.
* Added a rotating loading indicator while the assistant is processing.

* **Tests**
* Added coverage confirming Markdown formatting for assistant responses
and plain-text rendering for user messages.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## Summary

- raise the remote AI provider response timeout from 60 seconds to 180
seconds
- use one shared timeout for Claude, OpenAI, custom provider URLs, and
Azure OpenAI
- allow larger AI Assistant generations to finish instead of failing at
the one-minute mark

The Local LLM client keeps its existing 120-second timeout.

## Testing

- server Spotless/pre-commit checks passed across all modules
- CI server tests

## Linear


https://linear.app/appsmith/issue/APP-15735/replace-internal-appsmith-app-with-native-co-pilot-component

## Automation

/ok-to-test tags="@tag.Widget, @tag.IDE"

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/31090811946>
> Commit: cbbb640
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=31090811946&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.Widget, @tag.IDE`
> Spec:
> <hr>Thu, 06 Aug 2026 11:03:38 UTC
<!-- end of auto-generated comment: Cypress test results  -->


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
  * Increased the AI provider response timeout to 180 seconds.
* Improved reliability for Claude, OpenAI, custom endpoint, and Azure
OpenAI requests that require additional processing time.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
…) (#41980)

## What & why

Adds an **opt-out, same-instance Streamable HTTP MCP server** that lets
an MCP client (e.g. an AI agent) act as a specific Appsmith user. The
client authenticates with a **user-scoped bearer token**; the Node
service forwards that token to the existing `/api/v1` endpoints, so
Spring Security reconstructs the real user and the existing
workspace/app/page ACLs authorize every operation. **No privileged or
instance-wide credential is used.**



## How it works

```
MCP client --(Bearer mcp_… token)--> Caddy /mcp --> Node MCP service --(forwards same token)--> /api/v1 --> Spring Security (real user) --> existing ACLs
```

### Server (CE, EE-overridable)
- `UserMcpToken` domain + repository + service + `McpTokenController`
for **create / list / revoke** of user-scoped tokens. Every layer
follows the CE-base + thin concrete-subclass split (`*CE` / `*CEImpl`)
so EE can override.
- Tokens are **SHA-256 pre-hashed then bcrypt-hashed at rest** (avoids
bcrypt's 72-byte truncation), plaintext returned exactly once, **max 10
active tokens/user**.
- A bearer `AuthenticationWebFilter` (only engages for the `mcp_`
prefix) reconstructs the token owner. Invalid / revoked / disabled-user
tokens return **401**.
- `Migration076` creates the `userMcpToken` indexes (the instance runs
with `auto-index-creation=false`, so `@Indexed` alone is inert).

### Node service (`app/client/packages/mcp`)
- Streamable HTTP transport bound to **loopback only**, `/health`
endpoint, request-body size cap, **per-request token revalidation**,
**per-session token binding** (constant-time compare), and **per-user +
global session caps**.
- Tools: `list_workspaces`, `list_applications`,
`get_application_context`, and `import_application_artifact` /
`import_partial_application_artifact` — writes go through the **existing
validated import / partial-import APIs** (no raw DSL/Mongo writes).

### Client
- MCP token management UI in the user profile (create / copy-once /
revoke).

### Rollout / deploy
- **Disabled by default — an admin opts in.** `APPSMITH_MCP_ENABLED`,
`APPSMITH_MCP_DATA_ENABLED` and `APPSMITH_MCP_JS_ENABLED` all default to
**off**, using allow-list semantics (`true|1|yes|on`): absent, blank,
and unrecognized values all mean disabled, so a typo in `docker.env`
fails safe. **Existing instances are unaffected by an upgrade** — the
entrypoint backfills the gates as `false`. Enable from **Admin Settings
→ MCP Server**.
- **While MCP is off:** `/mcp` returns a 404 `{"code":"mcp_disabled"}`
JSON (not the SPA's HTML); an already-issued `mcp_…` token is rejected
server-side with **401**, evaluated per request so the kill switch is
immediate and needs no restart; users **cannot create or rotate** tokens
(`AE-MCP-5049`), while `list`/`revoke` stay available so existing tokens
can still be cleaned up; and the Profile → MCP tokens section is hidden.
- MCP is never fatal to container health unless explicitly enabled, its
logs reach `docker logs`/`kubectl logs`, and they are size-capped on the
stacks volume.
- Dockerfile copy, dedicated `mcp-build` CI workflow, and a
`/mcp/health` route test.

## Testing
- **Java**: unit tests for token issuance/auth/revocation (real BCrypt),
the converter/manager, and a WebFilter test asserting invalid MCP bearer
→ 401 and non-MCP bearer → passthrough.
- **Node**: 13 tests — token forwarding, auth (missing / non-`mcp_` /
anonymous → 401), session binding & revalidation, TTL/expiry, per-user
(429) and global (503) caps, artifact validation, malformed/oversized
body handling. All pass.
- Ran Spotless, client `check-types`, ESLint (0 errors), and the MCP
package typecheck locally.

## Security review
Reviewed by a multi-agent council (architecture, security, QA,
data-migration, DX, UX, product). Key hardening landed from that review:
401 (not 500) on bad tokens, the CE/EE split, the index migration, the
`mcp_`-prefix + non-anonymous `/me` gate (closes an
unauthenticated-session DoS), per-user session cap, and the opt-in
deploy gate.

## Follow-ups (tracked, not blocking an opt-in ship)
- Gate the client "MCP Tokens" profile tab on the same enablement signal
(needs the flag surfaced to the client).
- End-user connection snippet (endpoint URL + client config) near the
token UI.
- Minor UX polish (revoke-failure toast, monospace token field,
destructive-button styling).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

## Automation
/ok-to-test tags="@tag.All"


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added an MCP server for authenticated app building, editing, data
access, publishing, and Git workflows.
* Added secure token creation, listing, rotation, revocation, naming,
expiry, and client configuration copying.
* Added admin controls for MCP, data tools, restricted JavaScript, and
token lifetime.
* Added structured layouts, widgets, themes, events, presets, queries,
governance safeguards, confirmations, audit history, rate limits, and
session controls.
  * Integrated MCP artifacts into Docker images and release builds.

* **Documentation**
* Added MCP setup, configuration, capabilities, and workflow
documentation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/31097538595>
> Commit: ffc7408
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=31097538595&attempt=2"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Thu, 06 Aug 2026 12:56:37 UTC
<!-- end of auto-generated comment: Cypress test results  -->

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: sondermanish <manish@appsmith.com>
…on (#15383)" (#42098)

reverting the CE pr due to EE build failures 
Reverts #41980
@appsmith-smithes
appsmith-smithes Bot requested a review from a team as a code owner August 7, 2026 10:29
@appsmith-smithes appsmith-smithes Bot added the ok-to-test Required label for CI label Aug 7, 2026
@appsmith-smithes
appsmith-smithes Bot merged commit f3af460 into master Aug 7, 2026
305 of 316 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ok-to-test Required label for CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants