From eb0ee3602d6bb1184e8dc17449fa2b4b8d03d28f Mon Sep 17 00:00:00 2001 From: Jose Castro Date: Mon, 14 Sep 2026 11:34:39 -0600 Subject: [PATCH 1/4] spec: Content Analytics Mode (persist/read-only) for issue #37521 Refs #37521 Co-Authored-By: Claude Sonnet 5 --- specs/37521-content-analytics-mode/spec.md | 184 +++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 specs/37521-content-analytics-mode/spec.md diff --git a/specs/37521-content-analytics-mode/spec.md b/specs/37521-content-analytics-mode/spec.md new file mode 100644 index 00000000000..d184f3698c2 --- /dev/null +++ b/specs/37521-content-analytics-mode/spec.md @@ -0,0 +1,184 @@ +# Feature Specification: Content Analytics Mode (Persist / Read Only) + +**Feature Branch**: `37521-content-analytics-mode` + +**Created**: 2026-09-14 + +**Status**: Draft + +**Type**: New Feature + +**Input**: User description: "Specification work for ticket: https://github.com/dotCMS/core/issues/37521" + +## Clarifications + +### Session 2026-09-14 + +- Q: Should changing Analytics Mode be recorded in an audit/activity log? → A: No special audit trail — matches existing Content Analytics app config save behavior (no App config field in dotCMS currently gets a dedicated audit-log entry on save). + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 - Stop an instance from persisting analytics events (Priority: P1) + +A customer runs a non-production dotCMS instance (e.g. UAT) that currently sends analytics +events into the same shared analytics dataset as their Production instance. They want to stop +that instance from writing data — without creating dedicated users or roles in Production, and +without anyone else's data being affected. + +**Why this priority**: This is the entire reason the feature exists — it replaces a much more +complex cross-environment access model (epic #37349) with a single per-instance switch. Without +this story there is no feature. + +**Independent Test**: On an instance already configured for Content Analytics, set Analytics +Mode to "Read Only", perform a tracked action (e.g. view a page), and confirm no new event +reaches the Content Analytics infrastructure while existing dashboard data for that +tenant/project is still visible. + +**Acceptance Scenarios**: + +1. **Given** an instance configured for Content Analytics with Analytics Mode set to "Read & + Write", **When** an admin changes Analytics Mode to "Read Only" and saves, **Then** the + instance stops sending analytics events from that point forward. +2. **Given** an instance with Analytics Mode set to "Read Only", **When** a site visitor + triggers a trackable action, **Then** no analytics event for that action is sent to the + Content Analytics infrastructure. +3. **Given** an instance with Analytics Mode set to "Read Only", **When** an admin changes + Analytics Mode back to "Read & Write" and saves, **Then** the instance resumes sending + analytics events without requiring a restart. + +--- + +### User Story 2 - Existing customers keep working unchanged after upgrade (Priority: P2) + +A customer already has Content Analytics configured and events flowing today. After upgrading +to the version that introduces Analytics Mode, nothing should change for them unless they +deliberately act. + +**Why this priority**: A silent behavior change on upgrade (events stopping without anyone +choosing that) would be a regression and a support incident. This must hold before the feature +can ship. + +**Independent Test**: Take an instance with Content Analytics already configured and events +flowing, upgrade it, and confirm events continue flowing with no configuration change required. + +**Acceptance Scenarios**: + +1. **Given** an instance that had Content Analytics configured before this feature existed, + **When** the instance is upgraded, **Then** its Analytics Mode is "Read & Write" and it + continues sending events exactly as before. + +--- + +### User Story 3 - Dashboards keep working regardless of mode (Priority: P3) + +An admin on a "Read Only" instance still wants to view that tenant/project's analytics +dashboards and reports. + +**Why this priority**: Read Only must mean "no ingest," not "no access" — otherwise the feature +removes value (viewing analytics) instead of just removing risk (unwanted writes). + +**Independent Test**: On an instance set to "Read Only", open the Content Analytics dashboard +and confirm existing data for the tenant/project renders normally. + +**Acceptance Scenarios**: + +1. **Given** an instance with Analytics Mode set to "Read Only", **When** an admin opens the + Content Analytics dashboard, **Then** existing analytics data for that tenant/project + displays exactly as it would on a "Read & Write" instance. + +--- + +### Edge Cases + +- Switching Analytics Mode from "Read & Write" to "Read Only" does not delete, hide, or alter + any analytics events already persisted — it only stops new events going forward. +- An instance that has never had the Content Analytics app configured shows no Analytics Mode + input and is unaffected by this feature. +- Analytics data for a tenant + project is never split or labeled by which environment produced + it — a "Read Only" instance and a "Read & Write" instance for the same tenant/project + contribute to (or read) the exact same dataset, with no environment distinction anywhere. +- An instance that the Platform Team has not enabled for Content Analytics access at all has no + Analytics Mode to set — that enablement gate is a precondition of this feature, not part of it. + +## Requirements *(mandatory)* + +### Functional Requirements + +- **FR-001**: System MUST provide an "Analytics Mode" input in the Content Analytics app + configuration with exactly two selectable values: "Read & Write" and "Read Only". +- **FR-002**: System MUST default Analytics Mode to "Read & Write" for every instance that had + Content Analytics already configured before this feature existed, so no customer's event flow + changes as a side effect of upgrading. +- **FR-003**: When Analytics Mode is "Read & Write", system MUST continue sending analytics + events to the Content Analytics infrastructure exactly as it does today. +- **FR-004**: When Analytics Mode is "Read Only", system MUST NOT send any analytics events to + the Content Analytics infrastructure. +- **FR-005**: System MUST apply an Analytics Mode change without requiring the dotCMS instance + to be restarted. +- **FR-006**: System MUST allow users to view existing analytics dashboards and reports + regardless of the instance's current Analytics Mode. +- **FR-007**: System MUST NOT classify, distinguish, or filter analytics data by originating + environment anywhere in the pipeline — all events for a given tenant and project are combined + with no environment dimension, superseding the environment-selector approach previously + proposed in epic #37349. +- **FR-008**: System MUST accept analytics events without requiring an environment identifier — + omitting it MUST NOT cause the event to be rejected, reversing the required-environment + validation introduced under #37407. +- **FR-009**: System MUST NOT require a dedicated audit/activity log entry for Analytics Mode + changes — it is saved like any other Content Analytics app configuration field, with no new + audit trail introduced by this feature. + +### Key Entities + +- **Instance Analytics Configuration**: A per-dotCMS-instance setting living in the Content + Analytics app configuration. Holds the Analytics Mode value ("Read & Write" or "Read Only"). + Only meaningful on an instance the Platform Team has already enabled for Content Analytics + access. +- **Analytics Event**: A tracked user/content interaction submitted to the Content Analytics + infrastructure. Identified by tenant and project; carries no environment identity. + +## Success Criteria *(mandatory)* + +### Measurable Outcomes + +- **SC-001**: An admin can change an instance's analytics-persistence behavior end-to-end + (open configuration, change mode, save) in under one minute, with no deployment or restart. +- **SC-002**: 100% of instances that were sending analytics data before this change continue + doing so immediately after upgrading, with zero customer action required. +- **SC-003**: An instance set to "Read Only" produces zero new analytics events in the shared + analytics dataset while retaining full, unchanged access to its existing dashboards and + reports. +- **SC-004**: Customers can control per-instance analytics persistence without creating or + managing any additional users or roles for cross-instance access — eliminating the operational + burden the original epic (#37349) set out to avoid. + +## Legacy Considerations *(dotCMS-specific — mandatory)* + +- **Existing behavior touched**: The Content Analytics app configuration (a dotCMS Cloud + feature) and the analytics event submission path from a dotCMS instance to the Content + Analytics infrastructure. This is modern, actively-developed functionality — not legacy + `com.dotmarketing.*` surface — though the underlying Apps/Integrations configuration framework + it builds on predates it. +- **Backward-compatibility expectations**: Every instance with Content Analytics already + configured must keep working exactly as before immediately after upgrade (default "Read & + Write"). The only contract change is relaxing the recently-introduced required `environment` + parameter on event submission back to optional — no other existing behavior changes. +- **Known related decisions**: Reverses the required, non-blank `environment` parameter decision + from epic #37349's 2026-09-09 amendment (formalized in the `dot-ca-event-manager` + constitution v1.2.0, Principle II, and specced under #37407). The `environment` column already + added to the ClickHouse schema is left in place, unused, with no migration performed. The plan + phase will formally consult `dotCMS/platform-adrs` (e.g. ADR-0022) for anything governing the + Content Analytics app configuration or event-submission contract. + +## Assumptions + +- The Platform Team's existing mechanism for enabling which instances may access the Content + Analytics infrastructure at all is unchanged by this feature; Analytics Mode only governs + persist-vs-read-only behavior on top of that existing gate. +- "Content Analytics app" refers to the existing per-instance App/Integration configuration + screen for Content Analytics — this feature adds a field to it, not a new settings page. +- Read Only is enforced by the dotCMS instance itself simply not submitting events; the Content + Analytics infrastructure requires no corresponding server-side rejection logic for this + feature. +- Users who can already edit the Content Analytics app configuration today are the same users + authorized to change Analytics Mode — no new permission model is introduced. From 5159ed4b331ddd62546ecdff0f01d68661dec117 Mon Sep 17 00:00:00 2001 From: Jose Castro Date: Mon, 14 Sep 2026 12:01:23 -0600 Subject: [PATCH 2/4] spec: address review feedback on Content Analytics Mode spec - FR-002a: default new (never-before-configured) instances to Read & Write too - Edge case: define "from that point forward" for in-flight/queued events at switch time - FR-004: scope "any analytics events" to Content Analytics ingest traffic only Refs #37521 Co-Authored-By: Claude Sonnet 5 --- specs/37521-content-analytics-mode/spec.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/specs/37521-content-analytics-mode/spec.md b/specs/37521-content-analytics-mode/spec.md index d184f3698c2..bd20cd04f50 100644 --- a/specs/37521-content-analytics-mode/spec.md +++ b/specs/37521-content-analytics-mode/spec.md @@ -92,6 +92,10 @@ and confirm existing data for the tenant/project renders normally. - Switching Analytics Mode from "Read & Write" to "Read Only" does not delete, hide, or alter any analytics events already persisted — it only stops new events going forward. +- "From that point forward" means no analytics event generated after the mode switch is saved + is submitted to the Content Analytics infrastructure — any event already queued or in flight + at the moment of the switch is not retroactively recalled once submission has started, but no + event generated after the switch is queued or sent. - An instance that has never had the Content Analytics app configured shows no Analytics Mode input and is unaffected by this feature. - Analytics data for a tenant + project is never split or labeled by which environment produced @@ -109,10 +113,17 @@ and confirm existing data for the tenant/project renders normally. - **FR-002**: System MUST default Analytics Mode to "Read & Write" for every instance that had Content Analytics already configured before this feature existed, so no customer's event flow changes as a side effect of upgrading. +- **FR-002a**: System MUST also default Analytics Mode to "Read & Write" when an admin + configures the Content Analytics app for the first time on an instance that never had it + configured before — new setups behave the same as upgraded ones; there is no scenario where + an instance ends up "Read Only" without an admin deliberately choosing it. - **FR-003**: When Analytics Mode is "Read & Write", system MUST continue sending analytics events to the Content Analytics infrastructure exactly as it does today. -- **FR-004**: When Analytics Mode is "Read Only", system MUST NOT send any analytics events to - the Content Analytics infrastructure. +- **FR-004**: When Analytics Mode is "Read Only", system MUST NOT send any Content Analytics + ingest events (page views, impressions, clicks, and other tracked content-interaction events) + to the Content Analytics infrastructure. This is scoped strictly to Content Analytics ingest + traffic — it does not affect any other, unrelated telemetry, health-check, or usage-reporting + signal the instance emits. - **FR-005**: System MUST apply an Analytics Mode change without requiring the dotCMS instance to be restarted. - **FR-006**: System MUST allow users to view existing analytics dashboards and reports From 9c74ca9494460d0b5c7cb4daa2d11b45065cbd9c Mon Sep 17 00:00:00 2001 From: Jose Castro Date: Mon, 14 Sep 2026 12:17:20 -0600 Subject: [PATCH 3/4] spec: resolve enforcement-point and Experiments scope gaps - FR-004/Assumptions: name the single instance-side ingest hand-off (verified in EventAnalyticsProxyResource + the analytics SDK's config.server+ANALYTICS_ENDPOINT) as the one gate that covers both server-rendered auto-tracking and headless/SPA SDK traffic, since neither posts directly to the Content Analytics infrastructure. Removes the apparent contradiction between FR-004 and the old enforcement wording. - Edge case + Legacy Considerations: Experiments (A/B testing) reads results via CubeJS against the same Content Analytics dataset (confirmed in ExperimentsAPIImpl / CubeJSClientFactoryImpl) - Read Only halting ingest is accepted to also halt new experiment result collection on that instance, not treated as a gap. Refs #37521 Co-Authored-By: Claude Sonnet 5 --- specs/37521-content-analytics-mode/spec.md | 33 ++++++++++++++++------ 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/specs/37521-content-analytics-mode/spec.md b/specs/37521-content-analytics-mode/spec.md index bd20cd04f50..ae98dd4bfda 100644 --- a/specs/37521-content-analytics-mode/spec.md +++ b/specs/37521-content-analytics-mode/spec.md @@ -103,6 +103,9 @@ and confirm existing data for the tenant/project renders normally. contribute to (or read) the exact same dataset, with no environment distinction anywhere. - An instance that the Platform Team has not enabled for Content Analytics access at all has no Analytics Mode to set — that enablement gate is a precondition of this feature, not part of it. +- An instance running an active Experiment (A/B test) that is switched to "Read Only" stops + collecting new experiment result data for that instance, for the same reason it stops + collecting any other analytics data — this is expected, not a defect. ## Requirements *(mandatory)* @@ -119,11 +122,15 @@ and confirm existing data for the tenant/project renders normally. an instance ends up "Read Only" without an admin deliberately choosing it. - **FR-003**: When Analytics Mode is "Read & Write", system MUST continue sending analytics events to the Content Analytics infrastructure exactly as it does today. -- **FR-004**: When Analytics Mode is "Read Only", system MUST NOT send any Content Analytics - ingest events (page views, impressions, clicks, and other tracked content-interaction events) - to the Content Analytics infrastructure. This is scoped strictly to Content Analytics ingest - traffic — it does not affect any other, unrelated telemetry, health-check, or usage-reporting - signal the instance emits. +- **FR-004**: When Analytics Mode is "Read Only", system MUST NOT forward any event to the + Content Analytics infrastructure's ingest endpoint. Every collection method — dotCMS's + built-in page/impression/click tracking on server-rendered pages, and the headless/SPA SDK + used by external applications — always submits events through this same dotCMS instance + first, never directly from the browser or an external app to the Content Analytics + infrastructure; gating that one instance-side ingest hand-off is therefore sufficient to cover + every collection method, with no separate client-side path left ungated. This is scoped + strictly to Content Analytics ingest traffic — it does not affect any other, unrelated + telemetry, health-check, or usage-reporting signal the instance emits. - **FR-005**: System MUST apply an Analytics Mode change without requiring the dotCMS instance to be restarted. - **FR-006**: System MUST allow users to view existing analytics dashboards and reports @@ -169,7 +176,9 @@ and confirm existing data for the tenant/project renders normally. feature) and the analytics event submission path from a dotCMS instance to the Content Analytics infrastructure. This is modern, actively-developed functionality — not legacy `com.dotmarketing.*` surface — though the underlying Apps/Integrations configuration framework - it builds on predates it. + it builds on predates it. Experiments (A/B testing) is a downstream consumer of the same + dataset (it queries the same analytics data to compute results) and is affected as a + consequence, though it is not itself modified by this feature. - **Backward-compatibility expectations**: Every instance with Content Analytics already configured must keep working exactly as before immediately after upgrade (default "Read & Write"). The only contract change is relaxing the recently-introduced required `environment` @@ -188,8 +197,14 @@ and confirm existing data for the tenant/project renders normally. persist-vs-read-only behavior on top of that existing gate. - "Content Analytics app" refers to the existing per-instance App/Integration configuration screen for Content Analytics — this feature adds a field to it, not a new settings page. -- Read Only is enforced by the dotCMS instance itself simply not submitting events; the Content - Analytics infrastructure requires no corresponding server-side rejection logic for this - feature. +- Read Only is enforced entirely on the dotCMS instance side, at the single point through which + every event — regardless of collection method — already passes on its way to the Content + Analytics infrastructure; the infrastructure itself requires no new rejection logic of its + own for this feature. +- Experiments (A/B testing) results are computed from the same Content Analytics dataset this + feature gates. Setting an instance to Read Only is expected to also stop new experiment + result data from that instance — this is accepted, not treated as a gap to work around, since + an instance an admin has deliberately chosen not to persist analytics from cannot + simultaneously produce live experiment measurements. - Users who can already edit the Content Analytics app configuration today are the same users authorized to change Analytics Mode — no new permission model is introduced. From 34c0c56157d71ea548b0628c1b599de98a4a36d7 Mon Sep 17 00:00:00 2001 From: Jose Castro Date: Mon, 14 Sep 2026 12:25:26 -0600 Subject: [PATCH 4/4] spec: address clustering, load-bearing-assumption, and measurability findings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FR-005: clarify cluster-wide propagation uses the same existing cache-invalidation mechanism every other Content Analytics app config field already relies on (verified via AppsAPIImpl.invalidateCache() / CacheLocator.getAppsCache()) — no new mechanism, brief propagation delay is expected and acceptable. - Assumptions: flag the "events always route through the instance first" claim as the one load-bearing assumption the whole feature depends on; require /speckit-plan to re-trace it against the actual code rather than carry it forward unverified. - US1: add acceptance scenario 4 exercising the headless/SPA SDK path specifically, not just server-rendered tracking. - SC-002/SC-003: add concrete measurement methods; SC-003 measured instance-side since the shared dataset can't attribute events to a specific instance (per FR-007). Refs #37521 Co-Authored-By: Claude Sonnet 5 --- specs/37521-content-analytics-mode/spec.md | 29 +++++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/specs/37521-content-analytics-mode/spec.md b/specs/37521-content-analytics-mode/spec.md index ae98dd4bfda..476075506e9 100644 --- a/specs/37521-content-analytics-mode/spec.md +++ b/specs/37521-content-analytics-mode/spec.md @@ -45,6 +45,11 @@ tenant/project is still visible. 3. **Given** an instance with Analytics Mode set to "Read Only", **When** an admin changes Analytics Mode back to "Read & Write" and saves, **Then** the instance resumes sending analytics events without requiring a restart. +4. **Given** an instance with Analytics Mode set to "Read Only" whose content is consumed by a + headless/SPA application through the Content Analytics SDK (not a server-rendered page), + **When** that application triggers a tracked event, **Then** no event reaches the Content + Analytics infrastructure — the same guarantee holds for SDK-driven traffic as for + server-rendered page tracking. --- @@ -132,7 +137,12 @@ and confirm existing data for the tenant/project renders normally. strictly to Content Analytics ingest traffic — it does not affect any other, unrelated telemetry, health-check, or usage-reporting signal the instance emits. - **FR-005**: System MUST apply an Analytics Mode change without requiring the dotCMS instance - to be restarted. + to be restarted. On a clustered instance, the change MUST propagate to every node using the + same cluster-wide cache-invalidation mechanism every other Content Analytics app configuration + field already relies on — no new propagation mechanism, and no special same-node-only + guarantee, is introduced for this field. A brief window where a sibling node has not yet + received the change (matching that existing mechanism's normal propagation delay) is expected + and acceptable; nodes are not expected to diverge beyond it. - **FR-006**: System MUST allow users to view existing analytics dashboards and reports regardless of the instance's current Analytics Mode. - **FR-007**: System MUST NOT classify, distinguish, or filter analytics data by originating @@ -162,10 +172,15 @@ and confirm existing data for the tenant/project renders normally. - **SC-001**: An admin can change an instance's analytics-persistence behavior end-to-end (open configuration, change mode, save) in under one minute, with no deployment or restart. - **SC-002**: 100% of instances that were sending analytics data before this change continue - doing so immediately after upgrading, with zero customer action required. + doing so immediately after upgrading, with zero customer action required — measured by + comparing each instance's analytics event count for a fixed window immediately before and + after upgrade and confirming neither drops to zero nor decreases unexpectedly. - **SC-003**: An instance set to "Read Only" produces zero new analytics events in the shared analytics dataset while retaining full, unchanged access to its existing dashboards and - reports. + reports — measured, on the instance side (since the shared dataset does not distinguish which + instance contributed a given event, per FR-007), by confirming no outbound event submission + occurs for any tracked action performed while Read Only is active, and that the same dashboard + queries return unchanged data before and after the switch. - **SC-004**: Customers can control per-instance analytics persistence without creating or managing any additional users or roles for cross-instance access — eliminating the operational burden the original epic (#37349) set out to avoid. @@ -200,7 +215,13 @@ and confirm existing data for the tenant/project renders normally. - Read Only is enforced entirely on the dotCMS instance side, at the single point through which every event — regardless of collection method — already passes on its way to the Content Analytics infrastructure; the infrastructure itself requires no new rejection logic of its - own for this feature. + own for this feature. **This is the assumption the whole feature depends on** — if any + collection method (present or future) were found to submit events directly to the Content + Analytics infrastructure instead of through the instance, Read Only would silently leak for + that path. `/speckit-plan` MUST re-trace the actual ingest path for every current collection + method (server-rendered tracking and the headless/SPA SDK) against the code at plan time, + rather than carrying this forward as an unverified assumption, and Acceptance Scenario 4 above + MUST be covered by a real test, not just server-rendered tracking. - Experiments (A/B testing) results are computed from the same Content Analytics dataset this feature gates. Setting an instance to Read Only is expected to also stop new experiment result data from that instance — this is accepted, not treated as a gap to work around, since