Migrate to Dynatrace New RUM Experience; single loading mechanism - #425
Draft
redbugz wants to merge 37 commits into
Draft
Migrate to Dynatrace New RUM Experience; single loading mechanism#425redbugz wants to merge 37 commits into
redbugz wants to merge 37 commits into
Conversation
- Add new inline scripts for all three environments (int, beta, prod) with agent version 10337260504112723 - Update dynatrace.ejs with frontier_snow_dynatraceNewRUM feature flag for gradual rollout - When new flag is ON: use 1.329+ version with enhanced data collection (owasp=1, uxrgce=1) - When new flag is OFF: use existing RUM version (backward compatible) - All three mechanisms supported: asyncCS-script, asyncCS-inline, global-cdn - New CDN URLs use SRI integrity hashes for added security - Existing frontier_snow_dynatraceRUM flag unchanged (still controls mechanism selection) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Add fetch-dynatrace-scripts.js helper for automated future RUM updates - Fetches latest scripts from Dynatrace API - Auto-writes inline scripts to _inline_*_new.ejs files - Displays CDN URLs and integrity hashes in copy-paste format - Add DYNATRACE_RUM_UPDATE.md with complete update procedures - Documents API setup, entity IDs, and testing procedures - Enables maintainers to automate RUM upgrades in the future Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Report the active loading mechanism (asyncCS-script, asyncCS-inline, or global-cdn) as a custom metric to Dynatrace. This enables direct DQL queries to correlate loading mechanism with Core Web Vitals performance (LCP, CLS, page load time). - Add window.dtrum.reportCustomMetric call to emit rum_loading_mechanism value - Bump version to 8.17.0-alpha.1 for telemetry feature Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
The RUM agent needs the data-dtconfig attribute (which includes reportUrl) to send beacons directly to the Dynatrace tenant instead of back through the app. Previously, only src and integrity were being extracted from the Dynatrace API response. Changes: - Extract and preserve data-dtconfig from complete script tags - Add cdnConfigNew object in dynatrace.ejs with per-environment configs - Apply data-dtconfig attribute to asyncCS-script and global-cdn mechanisms - Print config extraction confirmation in fetch script This fixes the 405 POST errors by ensuring RUM beacons are routed to the correct Dynatrace backend endpoint (reportUrl), not to the app. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Includes full data-dtconfig with proper reportUrl for direct beacon delivery to Dynatrace tenant. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
The new RUM script expects config in JSON format (data-config, data-appconfig, data-envconfig) which the fetch script provides in the inline script files. External script tags cannot reliably read data-* attributes, so we use the inline approach for both asyncCS-script and global-cdn mechanisms when new RUM is enabled. This fixes the initialization error: 'DT_RUM will not initialize: None of the supported configuration sources contain the required properties [revision, environmentId, app]' Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
…ease - Reflect version bump to 8.17.0-alpha.2 in package-lock.json - Make fetch-dynatrace-scripts.js executable Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Fixes RUM initialization by using inline script approach with proper JSON config format for new RUM. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Report rum_loading_mechanism metric immediately after each RUM script loads, rather than at the end of page. This ensures the custom metric is captured in the first page summary event before any beacons are sent. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Fixes telemetry timing to report RUM loading mechanism before first page summary beacon. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
asyncCS-script should load the script asynchronously to not block page rendering. Add missing async attribute to old RUM Edge CDN script. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This reverts commit 29ce2e3.
- Update fetch-dynatrace-scripts.js to call /api/v2/rum/inlineCode endpoint for actual JavaScript code - Write actual minified inline code to _inline_*_new.ejs files (300-460KB) instead of script tags - Fix dynatrace.ejs to properly differentiate the three mechanisms: * asyncCS-script: async external from CDN (Edge for old, Dynatrace for new) * asyncCS-inline: full inline embedding (300-460KB for new, ~35KB for old) * global-cdn: synchronous external from Dynatrace CDN - Each mechanism now clearly uses distinct loading patterns for telemetry differentiation This enables accurate performance comparison of mechanisms via Dynatrace telemetry. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Fetch and display: - /api/v2/rum/javaScriptTag (simple tag, 157 chars) - /api/v2/rum/oneAgentJavaScriptTagWithSri (SRI tag, ~1KB) - /api/v2/rum/inlineCode (inline code, 300-460KB) Shows both CDN URLs for comparison: basic variant vs new SRI variant. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Extract env values into separate helper function for reusability - Update dynatrace.ejs with per-env fallback pattern using locals.dynatrace - Generate dynatrace-rum-config.json for Snow to publish to CDN - Snow can inject fresh values at runtime via locals.dynatrace override - Clearer next steps in console output This enables decoupling: react-scripts has built-in fallback values, but Snow can override with latest values from dynatrace-rum-config.json CDN file. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Update dynatrace.ejs to support Snow providing fresh config values via res.locals.dynatrace, with fallback to hardcoded values. This enables: - Old Snow: transparently uses hardcoded fallback values - New Snow: overrides with fresh values from CDN config file - Old react-scripts + new Snow: new RUM works with stale but functional config - New react-scripts + old Snow: new RUM works with publish-time config For asyncCS-inline, also check for Snow-provided inline script before falling back to included file. This completes the progressive enhancement architecture where react-scripts carries current values at publish time, and Snow can override them dynamically without breaking older app/runtime combinations. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Script now publishes dynatrace-rum-config.json to S3 after updating local files. Uses AWS CLI (aws s3 cp) instead of SDK, which: - Leverages existing AWS credential infrastructure (~/.aws/credentials or env vars) - No additional Node dependencies needed - Simpler setup: just 'aws configure' or set AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY - Works with standard AWS credential chain (no custom keychain storage) Configuration: - S3_PUBLISH_BUCKET: S3 bucket for config file (default: frontier-rum-config) - S3_PUBLISH_REGION: AWS region (default: us-east-1) - Both can be overridden via environment variables Keychain setup now only stores Dynatrace API token (AWS uses standard auth). Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Simplify the configuration property names published to S3 and used by Snow: - cdnUrlsNew → cdnUrls - cdnIntegrityNew → cdnIntegrity - cdnConfigNew → cdnConfig - inlineScriptNew → inlineScript Updates: - fetch-dynatrace-scripts.js: generate cleaner property names - dynatrace.ejs: read from locals.dynatrace with cleaner keys - dynatrace-rum-config.json: updated config structure The 'New' postfix was redundant since these are already scoped to the new RUM. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Snow servers and other services can now fetch dynatrace-rum-config.json without requiring AWS credentials or special access. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
…ents Convert template literals to string concatenation in include() calls for asyncCS-inline, asyncCS-script, and global-cdn fallback branches. EJS parser cannot handle backticks inside template tags. Also consolidate reporting mechanism calls to reduce duplication.
EJS requires <%- %> (with hyphen) to output included file content. Control-flow syntax <% %> cannot execute include() function calls.
Revert to <% include(...) %> syntax without hyphen, matching the pattern in layout.ejs. Remove leading './' from path since include() resolves relative to views directory.
EJS include directive requires a static identifier or variable, not inline function calls. Pre-compute dynamic paths using string concatenation, then pass the variable to include for proper resolution.
…ents Convert template literals to string concatenation in include() calls for asyncCS-inline, asyncCS-script, and global-cdn fallback branches. EJS parser cannot handle backticks inside template tags. Use <%- include() %> with string concatenation to support dynamic path calculation.
Log which treatment and code path is taken during dynatrace initialization to confirm we're running the latest deployed version.
Replace optional chaining (?.) with standard property access checks. Pre-compute include paths as variables to avoid string concatenation in include() calls, which may confuse EJS parser.
The new RUM agent's minified JS contains the "<%" sequence, which EJS
include() misreads as an unterminated scriptlet ("Could not find matching
close tag"), causing a 500. Load the new agent exclusively via <script>
tags (SRI tag or _complete.js) instead of inlining, and remap each
treatment to a Dynatrace snippet format:
asyncCS-script -> OneAgent JS tag + SRI, async
asyncCS-inline -> OneAgent JS tag + SRI, sync (no longer inlines)
global-cdn -> _complete.js, async
- Rewrite fetch-dynatrace-scripts.js: drop /inlineCode fetch and
_inline_*_new.ejs generation; add cdnCompleteUrls; robust fallback
rewriter that preserves the locals-first progressive-enhancement guard
- Delete generated _inline_*_new.ejs; old-RUM _inline_*.ejs untouched
- Refresh CDN config to agent 10337260526121002; update docs and changelog
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…um-upgrade # Conflicts: # CHANGELOG-FRONTIER.md # package-lock.json # packages/react-scripts/package.json
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n fix - Preflight 'aws sts get-caller-identity' before any Dynatrace work; warn when AWS_PROFILE is unset and print SSO-aware setup guidance on failure (fail fast) - Rely on the standard AWS_PROFILE / credential chain (aws children inherit env) - Print the downloaded RUM agent version at the end of the run - Align KEYCHAIN_SERVICE_DYNATRACE with the stored keychain item + fix setup doc Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Consume the latest RUM release via fetch-dynatrace-scripts.js: refresh the dynatrace.ejs publish-time fallbacks and dynatrace-rum-config.json (also republished to S3). Supersedes agent 10337260526121002. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Drop the per-render '[dynatrace.ejs] Loaded' server log (redundant with the existing sendSessionProperties RUM telemetry; avoids prod log spam) - Sync package-lock.json self-version to 8.17.0 to match package.json (final release) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR upgrades Dynatrace RUM to a newer agent version and switches new-RUM loading to <script> tags (avoiding EJS include() compilation failures), adds runtime-config fallbacks via locals.dynatrace.*, and introduces tooling/docs to automate future RUM updates and publishing of a config artifact.
Changes:
- Reworked
dynatrace.ejsto support dual-flag rollout (mechanism vs version) and load new RUM exclusively via script tags with SRI/config support. - Added a fetch/publish automation script plus a generated
dynatrace-rum-config.jsonartifact for Snow runtime injection. - Bumped
@fs/react-scriptsto 8.17.0 and documented/released the change.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/react-scripts/layout/views/partials/dynatrace.ejs | Adds new-RUM script-tag branches, locals-first runtime config, and dual-flag gating. |
| packages/react-scripts/scripts/fetch-dynatrace-scripts.js | New automation script to fetch Dynatrace tags, update EJS fallbacks, generate config JSON, and publish to S3. |
| packages/react-scripts/scripts/dynatrace-rum-config.json | Generated per-env CDN URL/SRI/config values for Snow to consume at runtime. |
| packages/react-scripts/scripts/DYNATRACE_RUM_UPDATE.md | Operator runbook for fetching/publishing and validating treatment mappings. |
| packages/react-scripts/package.json | Version bump to 8.17.0. |
| package-lock.json | Lockfile version update for the react-scripts package entry. |
| CHANGELOG-FRONTIER.md | Release notes for 8.17.0 Dynatrace RUM changes. |
Comments suppressed due to low confidence (3)
packages/react-scripts/scripts/DYNATRACE_RUM_UPDATE.md:81
- This relative link points to ./partials/dynatrace.ejs, but the actual file lives under layout/views/partials/dynatrace.ejs. As written, the link is broken.
Two flags drive the experiment (see [dynatrace.ejs](./partials/dynatrace.ejs)):
packages/react-scripts/scripts/DYNATRACE_RUM_UPDATE.md:184
- These relative links are incorrect from the scripts/ directory. dynatrace.ejs is under layout/views/partials/, and fetch-dynatrace-scripts.js is the current file (same directory), so the links should be updated to avoid 404s in the runbook.
- [dynatrace.ejs](./partials/dynatrace.ejs) - Main RUM configuration file
- [fetch-dynatrace-scripts.js](./fetch-dynatrace-scripts.js) - The fetch script itself
packages/react-scripts/scripts/DYNATRACE_RUM_UPDATE.md:73
- The example snippet treats cdnIntegrityNew as a single string, but dynatrace.ejs defines cdnIntegrityNew as an environment-keyed object (and integrity values may differ per env). The example should reflect the actual shape.
```javascript
const cdnUrlsNew = {
int: '...', // Copy from script output
beta: '...', // Copy from script output
prod: '...' // Copy from script output
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- dynatrace.ejs: poll for window.dtrum before sendSessionProperties so the rum_loading_mechanism signal isn't dropped for async treatments (asyncCS-script / global-cdn), where the agent loads after the inline script - fetch-dynatrace-scripts.js: move temp-file cleanup into a finally block so it isn't left behind when the S3 upload fails - DYNATRACE_RUM_UPDATE.md: Step 2 now reflects that the script auto-updates the fallbacks and that integrity/config are per-environment (no single shared hash) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse Dynatrace RUM loading from three treatments across two flags down to one flag with three states, and remove all RUM Classic code paths. off no agent (kill switch, defined in int/beta/prod) asyncCS-inline versioned OneAgent tag + SRI, loaded sync anything else _complete.js from the global CDN, loaded async The default is a fallthrough rather than an equality check on 'global-cdn'. Retired treatment names, a renamed flag, and a Split outage returning 'control' must all still load RUM: failing closed produces a silent monitoring gap, which is the one failure mode invisible in the data itself. Remove frontier_snow_dynatraceNewRUM. It never controlled the New RUM Experience -- both its branches emitted the same URL and it only toggled `async`. New RUM enablement is the tenant's `enabledOnGrail` setting, toggled per application with no deploy. _complete.js from the Dynatrace CDN is the only mechanism that tracks tenant configuration without a react-scripts release. Two of the three previous treatments had been serving a RUM agent artifact dated 2022-11-04 to production, because refreshing a self-hosted artifact required a fetch-script run, a release, and a redeploy of every consuming app. The retained SRI arm covers both documented fallback cases at once: it is immutably cached for a year (if Dynatrace never adds a cache validator to _complete.js) and synchronous (no blind window if async proves to lose early interactions or errors). Delete the three _inline_*.ejs bootstraps (~105 KB). Inlining is permanently ruled out for New RUM: EJS include() compiles the file as a template and the minified agent contains the EJS open-delimiter sequence inside a string, which caused a production 500 (Could not find matching close tag for "<%"). Add dtWhenReady(which, fn) for both RUM APIs. enableManualPageDetection and window.dtinfo.appName previously sat behind `if (window.dtrum)`, which is always false under async loading -- they were silently inactive on the async treatments. Drop the rum_loading_mechanism session property: with one mechanism there is nothing to segment by. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
scripts/ is for scripts consumers of @fs/react-scripts run (build, start, test, init, eject). The Dynatrace fetch script, its config artifact, and the RUM docs are maintainer-only -- the fetch script needs a Dynatrace API token, AWS credentials and keychain access, and is documented as being run from a checkout rather than from node_modules. Because "scripts" is in package.json `files`, all of it was being published. Moving it to tools/, which is not in `files`, excludes it by construction -- no negation patterns to remember when adding future maintainer material. The fetch script also carried internal infrastructure details into the published artifact: the S3 bucket, the tenant URL, keychain service names, and the three APPLICATION-* entity IDs. Published package: 119 files / 392 KB -> 104 files / 247 KB, combined with the _inline_*.ejs removal in the previous commit. The only Dynatrace file still shipping is dynatrace.ejs, which consumers actually render. Also here: - Add DYNATRACE_RUM_MECHANISMS.md -- the option matrix, the candidates that were evaluated and rejected (inline bootstrap, self-hosted agent, auto-injection) with the case for each and why it lost, the decision rationale, revisit triggers, and the revival recipe. - Add beacon-harness/ with the retained raw JSONL from the run that measured New RUM's ~2.3x per-session upload increase. Standalone: its package.json is not picked up by the workspace, whose glob is packages/* (direct children only). - Fix paths broken by the move: the fetch script's relative path to dynatrace.ejs, and the doc cross-links. - Rewrite the unreleased 8.17.0 changelog entry, which described the superseded dual-flag design. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Migrates Frontier apps to the Dynatrace New RUM Experience (RUM on Grail) and reduces agent loading from three treatments across two feature flags to one flag with three states. Fixes a production 500, removes ~105 KB of dead agent bootstraps, and moves maintainer tooling out of the published package. Ships as
@fs/react-scripts8.17.0.Full analysis: Dynatrace RUM: Loading Mechanisms & Agent Management (FRDOCS). Decision record in-repo:
packages/react-scripts/tools/dynatrace/DYNATRACE_RUM_MECHANISMS.md.What ships
offasyncCS-inline_complete.jsfrom the global CDN, asyncfrontier_snow_dynatraceNewRUMis removed. It never controlled New RUM — both branches emitted the same URL and it only toggledasync. New RUM enablement is the tenant'senabledOnGrailsetting, per application, no deploy.Reasoned Changes
Single loading mechanism, fail-open default (dynatrace.ejs)
What: Replaced six code paths (3 treatments × old/new RUM) with two. The default is a fallthrough, not an equality check on
global-cdn.Why:
_complete.jsis the only mechanism that tracks tenant configuration without a react-scripts release. Sampling production during the evaluation found two of the three treatments serving a RUM agent artifact dated 2022-11-04 — refreshing a self-hosted artifact required a fetch-script run, a release, and a redeploy of every consuming app, and that chain had not completed since 2022.The fallthrough is deliberate: retired treatment names, a renamed flag, and a Split outage returning
controlmust all still load RUM. Failing closed produces a silent monitoring gap, which is the one failure mode invisible in the data itself. There is a comment saying so — please don't tidy it into=== 'global-cdn'.Retained sync SRI arm as the fallback
What: Kept one non-default mechanism: the versioned OneAgent tag + SRI, loaded synchronously, under the existing
asyncCS-inlinetreatment name.Why: It covers both documented revisit triggers at once — immutably cached for a year (if Dynatrace never adds a cache validator to
_complete.js) and synchronous (no blind window ifasyncproves to lose early interactions). One arm rather than two.The treatment name is historical and describes neither its load mode nor its format; renaming would need a coordinated Split-plus-deploy change.
Deleted all RUM Classic code paths (−219 lines, ~105 KB)
What: Removed
edgeUrls, the oldcdnUrls, and the three_inline_*.ejsbootstraps.Why: Inlining is permanently ruled out for New RUM, not just deferred. EJS
include()compiles the file as a template and the minified agent contains the EJS open-delimiter sequence inside a character-class string — this caused a production 500 (Could not find matching close tag for "<%"). It also re-shipped 300–460 KB in every HTML response with no caching.Async readiness helper (layout.ejs)
What: Added
dtWhenReady(which, fn)for both RUM APIs;enableManualPageDetectionandwindow.dtinfo.appNameno longer sit behindif (window.dtrum).Why: That guard is always false under async loading, so both were silently inactive on the async treatments — manual page detection quietly fell back to automatic, and
dtinfo.appNamewas never set. Verified fixed on int (see Testing).Maintainer tooling moved out of the published package
What:
fetch-dynatrace-scripts.js, its config artifact, and the RUM docs moved fromscripts/totools/dynatrace/.Why:
scripts/is inpackage.jsonfiles, so all of it was being published to consumers — including a script that needs a Dynatrace API token, AWS credentials and keychain access, and that carries internal infrastructure details (S3 bucket, tenant URL, keychain service names, the threeAPPLICATION-*entity IDs).tools/is not infiles, so exclusion is by construction rather than by remembering a negation pattern.Published package: 119 files / 392 KB → 104 files / 247 KB. The only Dynatrace file still shipping is
dynatrace.ejs, which consumers actually render.Decision record and measurement harness
What:
DYNATRACE_RUM_MECHANISMS.md(option matrix, candidates evaluated and rejected, revisit triggers, revival recipe) andbeacon-harness/with retained raw JSONL.Why: The rejected candidates — inline bootstrap, self-hosted agent, auto-injection — each had a real case for them and lost for recorded reasons. Without that written down they get re-proposed. The harness measured New RUM's ~2.3× per-session upload increase and is the tool for re-verifying it after prod enablement.
Measurements behind the decision
_complete.jscachingmax-age=86400, noETag/Last-Modified→ full re-download every 24 hPerformance was a tie across mechanisms, so the decision was made on maintenance and freshness.
Risk Assessment
Behaviour change on deploy: the tag becomes
async. Production currently renders it synchronously in<head>, so every page render blocks onjs-cdn.dynatrace.com. Async removes that render-path dependency at no measured FCP cost, but introduces a blind window — measured at 925 ms on int — during which early clicks, XHRs and errors are not captured. CWV and navigation timing are recoverable retroactively via bufferedPerformanceObserver, so the cost is early interactions, not page-performance data.Revert path: flip the flag to
asyncCS-inline(sync, no blind window) oroff. No deploy required.Watch after rollout: RUM session volume for a step change across the async transition. Note the healthy sessions-per-render baseline is ~33%, not 100% —
costAndTrafficControl: 33means one session in three is monitored by design.Ordering constraint for prod: agent 1.341 is missing three of the four Gen3 API methods the RUM JavaScript SDK requires; 1.343 has all four. Prod is on
PREVIOUS_STABLE. Move the version channel and re-run the fetch script before enablingenabledOnGrail, or API-reported session properties silently will not land.Not addressed here:
layout.ejsinjects only whenNODE_ENV === 'production'and only where the layout renders, so custom error pages and 500s get no RUM. Pre-existing and independent of mechanism choice.Testing
Verified on
frontier-app-reactint with8.17.0-alpha.17deployed:Template rendering asserted for every flag state, including unknown ones:
npm pack --dry-runconfirms zero files fromtools/in the published package.Review hotspots
dynatrace.ejs— intentional, see the comment above it.tools/is not inpackage.jsonfiles— that is what excludes maintainer material. Addingtoolstofileswould silently re-publish it.cdnConfigNewstrings were not retyped — the diff edits around them, so the ~1 KBdata-dtconfigvalues are byte-intact.Follow-ups (not in this PR)
ETagon_complete.js. If granted, the retained SRI arm can be removed entirely.fetch-dynatrace-scripts.jsimmediately after prod moves toLATEST_STABLE— prod's SRI fallback is still 1.341 and the retained arm does not advance on its own.locals.dynatrace.*in production (fs-webdev/snowfeat/dynatrace-rum-config-injection, not merged). Until then every value comes from the baked fallback.