Skip to content

[pull] release from appsmithorg:release - #294

Merged
pull[bot] merged 9 commits into
code:releasefrom
appsmithorg:release
Jul 28, 2026
Merged

[pull] release from appsmithorg:release#294
pull[bot] merged 9 commits into
code:releasefrom
appsmithorg:release

Conversation

@pull

@pull pull Bot commented Jul 28, 2026

Copy link
Copy Markdown

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

salevine and others added 9 commits July 9, 2026 10:43
The configure_block_event_tracking_for_anonymous_users flag left two gaps
that let anonymous-user events through when it was on:

- Client (shouldTrackUser): an active license short-circuited the flag,
  so licensed EE/cloud instances always tracked anonymous users. Removed
  the licenseActive bypass so the flag is honored on all instances.
- Server (AnalyticsServiceCEImpl.sendEvent): the flag was only checked in
  sendObjectEvent. Direct sendEvent callers passing an anonymous userId
  bypassed it. Added a gate on the public sendEvent that blocks anonymous
  userIds before the x-anonymous-user-id is resolved, keeping the existing
  sendObjectEvent check for the session-user (signup) path. sendObjectEvent
  now routes through the extracted private sendEventInternal to avoid a
  redundant (Redis-backed) flag check on the hot anonymous path.

usage-pulse billing/seat metering is intentionally out of scope.

Adds unit tests: client shouldTrackUser matrix (incl. the license-bypass
regression guard) and a server sendEvent anonymous-block guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…S_USERNAME

Code-review follow-ups on the anonymous-tracking gate:

- sendEvent's anonymous gate now handles featureFlagService.check()
  errors with onErrorResume, failing closed (event dropped, chain
  completes) instead of propagating the error into previously
  fire-and-forget callers like GlobalExceptionHandler. Adds a
  regression test for the error path.
- Align gate style with repo convention: raw if (isBlocked) and plain
  Mono.empty() (Reactor forbids null onNext, so the defensive forms
  bought nothing).
- Client: use the existing ANONYMOUS_USERNAME constant from
  userConstants instead of the hardcoded "anonymousUser" literal in
  shouldTrackUser and its test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nymous users

When configure_block_event_tracking_for_anonymous_users blocks Segment
init, segmentAnalytics exists but has no user, so
AnalyticsUtil.getAnonymousId() returns undefined. The telemetry-enabled
anonymous branch of getUsagePulsePayload then sent no anonymousUserId,
breaking anonymous usage counting.

Extract the existing local-fallback-id logic into
getOrCreateFallbackAnonymousId() and fall back to it whenever the Segment
id is unavailable, keeping usage-pulse's identity independent of Segment
analytics blocking. The helper also guards localStorage access so a
private-mode/quota throw returns a per-call id instead of dropping the
pulse.

Adds unit coverage for getUsagePulsePayload across the telemetry
on/off and Segment-available/unavailable branches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The anonymous-user gate in sendObjectEvent lacked the onErrorResume that
sendEvent got, so a flag-service/Redis error propagated into the business
flows this analytics call is chained into (EXECUTE_ACTION, page VIEW,
signup), failing them with a 500. Mirror the fail-closed handling: warn
and drop the anonymous event, still emitting the original object.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011JhX44ugwPpHn9JrzQvqWD
…41973)

## Description

Makes the `configure_block_event_tracking_for_anonymous_users` feature
flag **completely** turn off anonymous-user event tracking. Two gaps let
anonymous events through when the flag was on:

### Gap 1 — client license bypass
(`app/client/src/ce/sagas/userSagas.tsx`)
`shouldTrackUser` short-circuited on an active license:
```
isAnonymous && (licenseActive || (telemetryOn && !featureFlag))
```
so licensed EE/cloud instances tracked anonymous users regardless of the
flag. Removed the `licenseActive` bypass — the flag is now honored on
**all** instances.

### Gap 2 — ungated direct `sendEvent` path (`AnalyticsServiceCEImpl`)
The flag was only checked in `sendObjectEvent`. Direct callers of
`sendEvent(event, userId, props)` with an anonymous userId bypassed it
(and that path resolves the anonymous user to the client
`x-anonymous-user-id`). Added a gate on the public `sendEvent` that
blocks anonymous userIds **before** id resolution, and it fails closed
if the flag state can't be resolved (drops the event, completes the
chain). The existing `sendObjectEvent` check is kept (it governs the
session-user/signup path, where `sendEvent` receives the new user's
email rather than `"anonymousUser"`). `sendObjectEvent` now routes
through the extracted private `sendEventInternal` to avoid a redundant
(Redis-backed) flag check on the hot anonymous path (published-app page
views / action executions).

### Scope
- Behavior is **opt-in**: the flag defaults to `false`, so existing
instances are unchanged until an admin enables it.
- **Out of scope (intentional):** the usage-pulse channel
(`/api/v1/usage-pulse`) still emits the anonymous ID — that feeds
billing/seat metering, not Segment analytics, and is treated separately.

### Tests
- **Client** — new `userSagas.test.ts` covering the `shouldTrackUser`
matrix, including the regression guard that anonymous + telemetry-on +
flag-on returns `false` on a licensed instance.
- **Server** — new `AnalyticsServiceCEImplTest` cases: a direct
anonymous `sendEvent` enqueues nothing when the flag is on, and fails
closed (no enqueue, no error) when the flag check errors.

Ticket: #15380

## 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/30322009616>
> Commit: 6b500e2
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=30322009616&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Tue, 28 Jul 2026 03:13:55 UTC
<!-- end of auto-generated comment: Cypress test results  -->


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


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

* **New Features**
* Enhanced anonymous-user analytics controls using the
`configure_block_event_tracking_for_anonymous_users` feature flag.
* Usage pulse now uses a stable anonymous identifier with resilient
local fallback behavior.

* **Bug Fixes**
* Anonymous event tracking is now correctly suppressed when the flag
blocks tracking, including fail-closed behavior when the flag can’t be
evaluated.
* Improved anonymous detection using the shared anonymous username
constant.

* **Tests**
* Added/extended tests covering anonymous tracking decisions, event
suppression, and anonymous identifier fallback persistence.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Wyatt Walter <wyattwalter@gmail.com>
@pull pull Bot locked and limited conversation to collaborators Jul 28, 2026
@pull pull Bot added the ⤵️ pull label Jul 28, 2026
@pull
pull Bot merged commit 1ba63c4 into code:release Jul 28, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants