Skip to content

[APPS-2945] Update: switch the apps plugin's static checks to the Node backend runtime (v2) - #557

Open
tyffical wants to merge 1 commit into
tiffany.trinh/apps-2961-parallel-local-executionfrom
tiffany.trinh/apps-2945-follow-terrapin-flag
Open

tyffical wants to merge 1 commit into
tiffany.trinh/apps-2961-parallel-local-executionfrom
tiffany.trinh/apps-2945-follow-terrapin-flag

Conversation

@tyffical

@tyffical tyffical commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Merges now; the build-plugins release that ships it waits until the backend runtime switch covers every production org, then the version is bumped.

Motivation

Architecture

 .backend.* transform   dev-server module-graph walk   production backend build (moduleParsed)
          └────────────────────────┬───────────────────────────────┘
                                   ▼
                runBackendStaticChecks(ast, file, log, scope)
                                   ▼
                rejectGlobalsMissingFromNode
                  XMLHttpRequest, EventSource, Deno  → error with a hint
                  feature checks (typeof X, if (globalThis.X), 'X' in globalThis)  → allowed
                  fetch, WebSocket, Node built-ins   → allowed
  • Every call site keeps its signature; only what runBackendStaticChecks enforces changes.
  • The ambient-global walker still follows globalThis/global members, destructures, const aliases and self-references, now for the three names Node lacks.

Changes

13 changes across run-backend-static-checks.ts, reject-restricted-globals.ts, reject-node-builtin-imports.ts, warn-divergent-globals.ts, ambient-global-access.ts, constants.ts, vite/index.ts, README.md, call-site comments, tests and fixtures
What changed File
Run only v2's check, which rejects XMLHttpRequest, EventSource and Deno, each with its own hint. packages/plugins/apps/src/backend/ast-parsing/run-backend-static-checks.ts, packages/plugins/apps/src/backend/ast-parsing/reject-restricted-globals.ts
Remove v1's network-global check, which rejected fetch, WebSocket and the like. packages/plugins/apps/src/backend/ast-parsing/reject-restricted-globals.ts
Remove v1's Node built-in import check. packages/plugins/apps/src/backend/ast-parsing/reject-node-builtin-imports.ts (deleted, with its test)
Remove the crypto/Intl warning, which compared local Node with production Deno. packages/plugins/apps/src/backend/ast-parsing/warn-divergent-globals.ts (deleted, with its test)
Remove the walker's bulk-copy detection (rest destructures, spreads, Object.assign/values/entries), which only v1's checks used. packages/plugins/apps/src/backend/ast-parsing/ambient-global-access.ts
Let feature checks pass: typeof X, and globalThis.X or globalThis?.X tested in an if, ?:, loop, switch, !, Boolean() or equality, or on the left of &&/||/??, also as a lower esbuild target rewrites them; a bare if (Deno) or a later use stays rejected. packages/plugins/apps/src/backend/ast-parsing/ambient-global-access.ts
Let a polyfill be installed on the global (=, ??=, ||=); assigning one of its members, such as globalThis.Deno.cwd = f, still reads it and is rejected. packages/plugins/apps/src/backend/ast-parsing/ambient-global-access.ts
Warn once at dev-server start, whether calls run in their own process or in the dev server's, when local Node's major version isn't the backend runtime's (24), or is older than 22, the first with a global WebSocket. packages/plugins/apps/src/vite/index.ts
Add the NODE_BACKEND_RUNTIME label and its NODE_BACKEND_RUNTIME_NODE_MAJOR, which the hints and tests share. packages/plugins/apps/src/constants.ts
Reword errors and comments that described banned imports. vite/backend-static-checks-plugin.ts, vite/index.ts, vite/dev-server-module-graph.ts, vite/local-execution.ts, vite/dev-server.ts
Document the backend runtime's rules, feature checks, polyfill installs, its Node major version and the minimum local Node. packages/plugins/apps/README.md
Retarget the walker's alias, destructure and self-reference cases to XMLHttpRequest, test feature checks, the Node warning, and that call sites accept fetch and node:os and reject Deno. reject-restricted-globals.test.ts, run-backend-static-checks.test.ts, index.test.ts, vite/*.test.ts
Rename the rejected-helper fixtures to say what they use. packages/tests/src/_jest/fixtures/apps_backend_project/helperUsingDeno.ts, viaDenoHelper.backend.ts

QA Instructions

yarn typecheck:all && yarn lint && yarn cli integrity
# Expected: all exit 0, integrity leaves no file changes ✅ VERIFIED
yarn build:all
# Expected: exit 0; the published plugins' dist, which the bundling tests read, includes local-execution-child.mjs ✅ VERIFIED
yarn test:unit packages/plugins/apps
# Expected: Test Suites: 39 total; Tests: 1025 total, all passed except the 15 macOS /var tests below ✅ VERIFIED
yarn test:unit
# Expected: Test Suites: 131 total; Tests: 1 skipped, 3617 total, all passed except the same 15 ✅ VERIFIED
TMPDIR=/private/tmp yarn test:unit packages/plugins/apps/src/vite/manifest-tags.integration.test.ts packages/plugins/apps/src/vite/parameters.integration.test.ts
# Expected: Test Suites: 2 passed; Tests: 33 passed, 33 total ✅ VERIFIED
  • Manual QA runs a scaffolded app (Vite 8) against a Datadog staging org with this branch's packed @datadog/vite-plugin, using dd-auth API keys.
    • install-plugin.sh builds and installs the branch's plugin; qa-run.sh starts the dev server, runs each fixture's functions through /__dd/executeAction and prints the plugin's warnings and every request the process made, logged by log-requests.mjs.
    • QA_DIR is the directory holding the scripts.
    • Every run below uses QA_APP=~/qa-apps-2945/qa-app-held-stack, a copy of the Vite 8 scaffold, unless its command sets QA_APP.
QA helper scripts
  • install-plugin.sh:
#!/usr/bin/env bash
# Usage: install-plugin.sh <pr-number> <worktree-name>
# Builds the worktree's packages, packs @datadog/vite-plugin to vite-plugin-<pr>.tgz here, and installs it into the
# QA scaffold (QA_APP, default ~/qa-apps-2945/qa-app). Prints the commit it was built from.
set -eu
QA_DIR="$(cd "$(dirname "$0")" && pwd)"
W="$HOME/go/src/github.com/DataDog/build-plugins/.claude/worktrees/$2"
echo "building $(git -C "$W" log --oneline -1)"
(cd "$W" && yarn build:all > "$QA_DIR/logs/build-$1.log" 2>&1)
(cd "$W/packages/published/vite-plugin" && yarn pack --out "$QA_DIR/vite-plugin-$1.tgz" > /dev/null)
cd "${QA_APP:-$HOME/qa-apps-2945/qa-app}"
npm install "$QA_DIR/vite-plugin-$1.tgz" > "$QA_DIR/logs/install-$1.log" 2>&1
echo "installed @datadog/vite-plugin $(node -p "require('@datadog/vite-plugin/package.json').version") from vite-plugin-$1.tgz"
  • qa-run.sh:
#!/usr/bin/env bash
# Usage: qa-run.sh <development|dev-verify> <fixture>...   (run under dd-auth, so API keys are set)
# Starts the scaffold's Vite dev server (QA_APP, default ~/qa-apps-2945/qa-app) on 5173 in the given mode with every
# fetch the process makes logged, transforms each src/<fixture>.backend.ts, runs each accepted fixture's exported
# functions once through /__dd/executeAction (dev-verify sends it to the cloud), and prints the plugin's warnings and
# cloud log lines, then every request the process made. QA_NODE picks the Node binary and QA_NODE_OPTIONS adds Node
# options (such as --inspect) to the dev server's process.
set -u
MODE="$1"; shift
# Fixtures live in src/; QA_URL_PREFIX is their path from Vite's root (empty for an app with root: 'src').
URL_PREFIX="${QA_URL_PREFIX-src/}"
QA_DIR="$(cd "$(dirname "$0")" && pwd)"
mkdir -p "$QA_DIR/logs"
# The request log lives in the temp dir, since a backend function's fetch appends to it inside the guarded run.
LOG="$QA_DIR/logs/vite-$MODE-$$.log"; NET_LOG="$(node -p "require('os').tmpdir()")/qa-net-$MODE-$$.log"; : > "$NET_LOG"
cd "${QA_APP:-$HOME/qa-apps-2945/qa-app}"
if [ -n "$(lsof -ti tcp:5173 -sTCP:LISTEN)" ]; then echo "port 5173 is busy"; exit 1; fi
env -u DD_OAUTH_ACCESS_TOKEN -u DATADOG_OAUTH_ACCESS_TOKEN DD_SITE=datad0g.com QA_NET_LOG="$NET_LOG" \
    NODE_OPTIONS="--import $QA_DIR/log-requests.mjs${QA_EXTRA_IMPORT:+ --import $QA_EXTRA_IMPORT}${QA_NODE_OPTIONS:+ $QA_NODE_OPTIONS}" \
    "${QA_NODE:-node}" node_modules/vite/bin/vite.js --mode "$MODE" --port 5173 --strictPort < /dev/null > "$LOG" 2>&1 &
for _ in $(seq 1 180); do curl -s -o /dev/null http://localhost:5173/ && break; sleep 1; done
for fixture in "$@"; do
  module="$(curl -s "http://localhost:5173/$URL_PREFIX$fixture.backend.ts")"
  if ! printf %s "$module" | grep -q executeBackendFunction; then
    message="$(printf %s "$module" | sed 's/\x1b\[[0-9;]*m//g' | grep -oE '"message":"([^"\\]|\\.)*' | head -1)"
    echo "$fixture: rejected: ${message:0:180}"
    continue
  fi
  echo "$fixture: accepted"
  for fn in $(sed -n 's/^export async function \([A-Za-z0-9_]*\).*/\1/p' "src/$fixture.backend.ts"); do
    FN="$(printf %s "$URL_PREFIX$fixture" | shasum -a 256 | cut -d' ' -f1).$fn"
    resp="$(curl -s -m 120 -w '\n%{http_code}' -X POST -H 'Content-Type: application/json' \
      -d "{\"functionName\":\"$FN\",\"args\":[\"QA\"]}" http://localhost:5173/__dd/executeAction)"
    echo "  $fn: $(printf %s "$resp" | sed '$d' | cut -c1-230) [HTTP $(printf %s "$resp" | tail -1)]"
  done
done
echo "plugin log:"
sed 's/\x1b\[[0-9;]*m//g' "$LOG" | grep -E "[|[](warn|error)\||via cloud as|script limit|in a child process|Debugger listening" | sed -E 's/(pid|temp dir|ws:\/\/127\.0\.0\.1:)[^,)]*/\1 <redacted>/g' | cut -c1-230
echo "requests made:"
sed -E "s#https://(api\.)?datad0g\.com#<staging>#" "$NET_LOG" | sed -E 's#/execution-long-polling/[^ ]+#/execution-long-polling/<receipt>#' | sort | uniq -c
kill "$(lsof -ti tcp:5173 -sTCP:LISTEN)" 2>/dev/null
for _ in $(seq 1 10); do [ -z "$(lsof -ti tcp:5173 -sTCP:LISTEN)" ] && break; sleep 1; done
lsof -ti tcp:5173 -sTCP:LISTEN || echo "server stopped"
  • log-requests.mjs:
// Preloaded with --import: appends the method and URL of every fetch the process makes to $QA_NET_LOG.
import { appendFileSync } from 'node:fs';

const realFetch = globalThis.fetch;
globalThis.fetch = (input, init) => {
    const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
    const method = init?.method ?? (typeof input === 'object' && 'method' in input ? input.method : 'GET');
    appendFileSync(process.env.QA_NET_LOG, `${method} ${url.split('?')[0]}\n`);
    return realFetch(input, init);
};
Local execution: fetch and node:os accepted, Deno rejected, a feature check passes, no runtime lookup
  • src/useFetch.backend.ts:
export async function getStatus() {
    const response = await fetch('https://example.com');
    return response.status;
}
  • src/useNode.backend.ts:
import os from 'os';

export async function getHostAndStatus() {
    const response = await fetch('https://example.com');
    return { host: os.hostname(), status: response.status };
}
  • src/useDeno.backend.ts:
export async function getCwd() {
    return Deno.cwd();
}
  • src/useFeatureCheck.backend.ts:
export async function detectRuntime() {
    const deno = typeof Deno !== 'undefined' || globalThis.Deno?.version !== undefined;
    return { deno, eventSource: 'EventSource' in globalThis };
}
cd "$QA_DIR" && QA_APP=~/qa-apps-2945/qa-app-held-stack ./install-plugin.sh 557 <this worktree>
dd-auth --domain dd.datad0g.com -- ./qa-run.sh development useFetch useNode useDeno useFeatureCheck | sed -E 's#/Users/tiffany.trinh/#~/#g'
# useFetch: accepted
#   getStatus: {"success":true,"result":{"data":200}} [HTTP 200]
# useNode: accepted
#   getHostAndStatus: {"success":true,"result":{"data":{"host":"COMP-JXV4463LMC","status":200}}} [HTTP 200]
# useDeno: rejected: "message":"\"Deno\" is not available in the Node backend runtime (v2). Use a Node API or a node: built-in import instead: ~/qa-apps-2945/qa-app-held-stack/src/us
# useFeatureCheck: accepted
#   detectRuntime: {"success":true,"result":{"data":{"deno":false,"eventSource":false}}} [HTTP 200]
# plugin log:
# [Qa App|warn|vite|git] No git remotes available, skipping git plugin. This is expected for a repository that has not been pushed yet.
# [Qa App|debug|vite|apps] Executing "getStatus" in a child process (pid <redacted>, temp dir <redacted>) with args
# [Qa App|debug|vite|apps] Executing "getHostAndStatus" in a child process (pid <redacted>, temp dir <redacted>) with args
# [Qa App|debug|vite|apps] Executing "detectRuntime" in a child process (pid <redacted>, temp dir <redacted>) with args
# requests made:
#       3 GET <staging>/api/v2/app-builder/queries/execution-long-polling/<receipt>
#       3 POST <staging>/api/v2/app-builder/queries/preview-async
#       1 POST https://browser-http-intake.logs.datadoghq.com/v1/input/pub44d5f4eb86e1392037b7501f7adc540e
# server stopped
# Expected: fetch and os run locally, each call in its own process; Deno fails the transform with the v2 hint; the feature check runs; no request reads the org's runtime (the log covers the dev server's process, since a call's own process doesn't inherit NODE_OPTIONS) ✅ VERIFIED
dev:verify on the real runtime: the same fixtures
dd-auth --domain dd.datad0g.com -- ./qa-run.sh dev-verify useFetch useNode useDeno useFeatureCheck
# useFetch: accepted
#   getStatus: {"success":true,"result":{"data":200}} [HTTP 200]
# useNode: accepted
#   getHostAndStatus: {"success":true,"result":{"data":{"host":"sandbox","status":200}}} [HTTP 200]
# useDeno: rejected: "message":"\"Deno\" is not available in the Node backend runtime (v2). Use a Node API or a node: built-in import instead: /Users/tiffany.trinh/qa-apps-2945/qa-app/src/useDeno.backe
# useFeatureCheck: accepted
#   detectRuntime: {"success":true,"result":{"data":{"deno":false,"eventSource":false}}} [HTTP 200]
# plugin log:
# [Qa App|warn|vite|git] No git remotes available, skipping git plugin. This is expected for a repository that has not been pushed yet.
# requests made:
#       3 GET <staging>/api/v2/app-builder/queries/execution-long-polling/<receipt>
#       3 POST <staging>/api/v2/app-builder/queries/preview-async
#       1 POST https://browser-http-intake.logs.datadoghq.com/v1/input/pub44d5f4eb86e1392037b7501f7adc540e
# server stopped
# Expected: the same verdicts, with the accepted functions running in the cloud (host sandbox) ✅ VERIFIED

Blast Radius

  • The release that ships this waits for every production org to run v2. Released earlier, a build would accept fetch or a Node built-in that fails in an org still on v1.
  • Every apps-plugin build and dev server: backend code using fetch, WebSocket or Node built-ins passes, XMLHttpRequest, EventSource and Deno fail with a hint, and the crypto/Intl warning is gone.
  • No feature flag, request or option; a dev server on a Node major other than 24, or older than 22, logs one warning.
  • v2 keeps v1's 30 s/60 s budget and 4011 timeout, with the runner capped at 256 MiB and 0.1 CPU.
  • Local execution's sandbox comes from [APPS-2961 Update: run each local backend function call in a fresh sandboxed process]([APPS-2961] Update: run each local backend function call in a fresh sandboxed process #608); [APPS-2945 Update: guard local execution with the Node backend runtime (v2) rules]([APPS-2945] Update: guard local execution with the Node backend runtime (v2) rules #563) applies v2's write rules to the in-process guard and points every local refusal to dev:verify.
  • Low risk once every org runs v2; high if released before.

Out of Scope / Follow-ups

9 items deferred
Item Status Next step
A watched global's value saved through ??, || or ?. and used later passes the check, then throws a TypeError on v2 Accepted None: a local run throws the same TypeError, since local Node lacks these globals too
A destructure with a default from the global (const { EventSource = P } = globalThis) is rejected Accepted Use ?? or import the polyfill by name
Bulk copies such as { ...globalThis } aren't followed, so all.XMLHttpRequest on a copy passes Accepted None: the check is best-effort, and the global would be missing at runtime
Browser globals (window, document) aren't checked Deferred Add them if real backend code hits them
require and __dirname aren't checked Accepted None: the v2 runner loads the script as an ES module (*.script.mjs), where they're undefined
child_process imports pass the static checks, but local execution blocks a subprocess when it runs Stacked on this PR [APPS-2945 Update: guard local execution with the Node backend runtime (v2) rules](#563): Node's permission model refuses it in a call's own process, the in-process guard elsewhere; the message points to dev:verify
v2 doesn't pass the developer's environment variables or Custom Credentials, so those process.env reads find nothing there Stacked on this PR [APPS-2945 Add: warn on process.env reads in backend functions](#565) warns on them
runBackendStaticChecks keeps its log argument while no check here logs Accepted The stacked env-read warning uses it
The jsSandboxWithActions and backendEnvironment: 'sandbox' paths are removed; restore them only if the backendEnvironment: sandbox override (Add a backendEnvironment override for app uploads) stays, which is unlikely Deferred Tiffany

Documentation

🤖 Generated with Claude Code

@tyffical

tyffical commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-07T04:35:03.872074Z 23556ed Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟢 Approval recommended

Runtime selection is consistently propagated, fails safely to v1, and has comprehensive coverage across affected execution paths.

Review effort: Balanced
Findings: None

What changed in this PR

Aligns backend static checks with each organization’s Terrapin feature-flag runtime while preserving v1 checks for cloud execution and fallback scenarios.

Changes:

  • Adds memoized, authenticated backend-runtime resolution with safe v1 fallback.
  • Threads runtime selection through build, transform, and local module-graph checks.
  • Adds runtime-specific tests and documentation.
File Description
packages/​plugins/​apps/​src/​backend-runtime.ts Resolves and caches the organization’s backend runtime.
packages/​plugins/​apps/​src/​backend-runtime.test.ts Tests authentication, fallback, timeout, caching, and logging.
packages/​plugins/​apps/​src/​backend/​ast-parsing/​run-backend-static-checks.ts Makes existing restrictions v1-only.
packages/​plugins/​apps/​src/​backend/​ast-parsing/​run-backend-static-checks.test.ts Verifies runtime-specific checks and warnings.
packages/​plugins/​apps/​src/​backend/​ast-parsing/​reject-restricted-globals.ts Updates runtime documentation.
packages/​plugins/​apps/​src/​vite/​index.ts Resolves and propagates runtime across Vite workflows.
packages/​plugins/​apps/​src/​vite/​index.test.ts Tests transforms, packaging, local execution, and dev:verify behavior.
packages/​plugins/​apps/​src/​vite/​backend-static-checks-plugin.ts Applies the selected runtime during nested builds.
packages/​plugins/​apps/​src/​vite/​backend-static-checks-plugin.test.ts Covers v1 and v2 plugin behavior.
packages/​plugins/​apps/​src/​vite/​build-backend-functions.ts Propagates runtime into production backend builds.
packages/​plugins/​apps/​src/​vite/​build-backend-functions.test.ts Tests runtime behavior in bundled dependency graphs.
packages/​plugins/​apps/​src/​vite/​dev-server-module-graph.ts Applies runtime-specific checks during local traversal.
packages/​plugins/​apps/​src/​vite/​dev-server-module-graph.test.ts Tests transitive module checks for both runtimes.
packages/​plugins/​apps/​src/​vite/​dev-server.ts Keeps cloud-generated bundles on v1.
packages/​plugins/​apps/​src/​vite/​dev-server.integration.test.ts Updates integration calls with explicit runtime.
packages/​plugins/​apps/​README.md Documents runtime resolution and resulting behavior.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 23556ed62a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/plugins/apps/src/backend-runtime.ts Outdated
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch 2 times, most recently from 6164a77 to a160fb7 Compare October 7, 2026 18:17
@datadog-prod-us1-6

datadog-prod-us1-6 Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Pipelines  Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: c499254 | Docs | View more details | Give us feedback!

@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch from 14c5415 to e898bea Compare October 7, 2026 18:33
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch 5 times, most recently from abf34ad to 892bda9 Compare October 15, 2026 01:04
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch 3 times, most recently from 2352fe9 to e7d5434 Compare October 15, 2026 19:07
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch 3 times, most recently from e44fe4a to 141d960 Compare October 16, 2026 00:47
@tyffical
tyffical marked this pull request as ready for review October 16, 2026 01:25
@tyffical
tyffical requested a review from a team as a code owner October 16, 2026 01:25
@tyffical
tyffical requested review from oliverli and removed request for a team October 16, 2026 01:25
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch 2 times, most recently from 04671dd to 696d422 Compare October 16, 2026 16:37
@tyffical tyffical changed the title [APPS-2945] Add: follow the org's Terrapin backend runtime in static checks [APPS-2945] Add: follow the org's backend runtime in static checks Oct 16, 2026
Comment thread packages/plugins/apps/src/backend-runtime.test.ts Outdated
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch 2 times, most recently from a64a6ad to 31ea49f Compare October 18, 2026 05:41
@tyffical
tyffical requested a review from a team as a code owner October 18, 2026 05:41
@tyffical
tyffical requested review from michaeldfoley and removed request for a team October 18, 2026 05:41
@tyffical tyffical changed the title [APPS-2945] Add: follow the org's backend runtime in static checks [APPS-2945] Update: switch the apps plugin's static checks to the Node backend runtime (v2) Oct 18, 2026
@tyffical
tyffical removed this pull request from stack #559 October 18, 2026 05:56
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch 2 times, most recently from ea71187 to e59b683 Compare October 20, 2026 23:58
…d runtime (v2)

Backend functions run as jsFunctionWithActions, which Datadog is moving
to the Node backend runtime (v2). Its static checks enforced the Deno
backend runtime (v1) rules, so they rejected code v2 runs.

The checks now apply v2's rules: Node built-in imports and Node's
network globals, such as fetch and WebSocket, are allowed, and
XMLHttpRequest, EventSource and Deno, which Node lacks, are rejected
with a hint; installing a polyfill on the global is allowed. The
v1-only checks are removed: the Node built-in import check, the
network-global check and the crypto/Intl warning.

Local execution runs on the developer's own Node, so the dev server now
warns once at start when its major version isn't v2's (24), beside the
existing warning for Node before 22, which lacks the global WebSocket.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tyffical
tyffical force-pushed the tiffany.trinh/apps-2945-follow-terrapin-flag branch from e59b683 to c499254 Compare October 22, 2026 16:46
@tyffical
tyffical changed the base branch from master to tiffany.trinh/apps-2961-parallel-local-execution October 22, 2026 16:46
@github-actions

Copy link
Copy Markdown

Live Debugger Runtime Benchmark

SDK-loaded dormant-probe runtime overhead, measured against an uninstrumented bundle in the same browser session.

Browser Workload Quality Per-call overhead upper
chrome Hot clean <= 4.73 ns
chrome Tiny clean <= 0.03 ns
firefox Hot clean <= 9.84 ns
firefox Tiny clean <= 0.18 ns
safari Hot clean <= 5.59 ns
safari Tiny clean <= 0.90 ns

What do the Tiny and Hot workloads represent?

Browser Debugger SDK: 7.16.1 · built 2026-10-21 · S3 ETag 1426183a

Full diagnostics
browser  workload  quality  per-call overhead upper  overhead upper          95% CI        A/A diag        block CI  acf(1)   baseline  instrumented                         samples
-------  --------  -------  -----------------------  --------------  --------------  --------------  --------------  ------  ---------  ------------  ------------------------------
chrome   Hot       clean                 <= 4.73 ns        <= 8.51%   4.71..4.73 ns  -0.01..0.01 ns   4.70..4.73 ns    0.02  50.943 ms     55.270 ms   102 (trim 20%, outliers 8.8%)
chrome   Tiny      clean                 <= 0.03 ns        <= 0.33%  -0.01..0.03 ns  -0.03..0.01 ns  -0.01..0.02 ns    0.00  55.673 ms     55.705 ms  102 (trim 20%, outliers 18.6%)
firefox  Hot       clean                 <= 9.84 ns       <= 35.86%   9.82..9.84 ns  -0.01..0.00 ns   9.82..9.84 ns    0.09  40.620 ms     55.160 ms   102 (trim 20%, outliers 5.9%)
firefox  Tiny      clean                 <= 0.18 ns        <= 1.18%   0.17..0.18 ns  -0.01..0.00 ns   0.17..0.18 ns    0.06  53.220 ms     53.820 ms  102 (trim 20%, outliers 11.8%)
safari   Hot       clean                 <= 5.59 ns       <= 20.55%   5.58..5.59 ns  -0.01..0.00 ns   5.58..5.59 ns   -0.02  45.940 ms     55.380 ms   102 (trim 20%, outliers 5.9%)
safari   Tiny      clean                 <= 0.90 ns       <= 21.35%   0.82..0.90 ns  -0.00..0.00 ns   0.82..0.90 ns   -0.14  29.000 ms     35.000 ms   102 (trim 20%, outliers 2.9%)

Raw samples are in the live-debugger-runtime-bench-results artifact.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants