Skip to content

fix(openfeature): support file-traced optional provider loading - #9324

Merged
BridgeAR merged 6 commits into
masterfrom
BridgeAR/2026-07-14-fix-openfeature-nft
Jul 16, 2026
Merged

fix(openfeature): support file-traced optional provider loading#9324
BridgeAR merged 6 commits into
masterfrom
BridgeAR/2026-07-14-fix-openfeature-nft

Conversation

@BridgeAR

Copy link
Copy Markdown
Member

Summary

Next.js standalone builds using pnpm omitted the optional OpenFeature provider because nft could not follow the shared dynamic optional-peer wrapper. This keeps the existing lazy loading behavior, makes the provider file-traceable, and adds dd-trace/openfeature as a fallback for build tools that do not recognize the wrapper.

Why

The optional provider must remain a peer dependency and must not be pulled into builds that do not use OpenFeature. The file-traceable wrapper and bundler rewrites preserve that opt-in behavior while allowing relocated standalone output to load the provider when it is installed or explicitly imported.

Refs: #8635

@dd-octo-sts

dd-octo-sts Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Overall package size

Self size: 6.78 MB
Deduped: 7.44 MB
No deduping: 7.44 MB

Dependency sizes | name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.3.1 | 122.62 kB | 438.86 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | dc-polyfill | 0.1.11 | 25.74 kB | 25.74 kB |

🤖 This report was automatically generated by heaviest-objects-in-the-universe

@pr-commenter

pr-commenter Bot commented Jul 14, 2026

Copy link
Copy Markdown

Benchmarks

Benchmark execution time: 2026-07-15 18:17:16

Comparing candidate commit 404a1fb in PR branch BridgeAR/2026-07-14-fix-openfeature-nft with baseline commit 4f01d4e in branch master.

📊 Benchmarking dashboard

Found 0 performance improvements and 0 performance regressions! Performance is the same for 2315 metrics, 43 unstable metrics.

Explanation

This is an A/B test comparing a candidate commit's performance against that of a baseline commit. Performance changes are noted in the tables below as:

  • 🟩 = significantly better candidate vs. baseline
  • 🟥 = significantly worse candidate vs. baseline

We compute a confidence interval (CI) over the relative difference of means between metrics from the candidate and baseline commits, considering the baseline as the reference.

If the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD), the change is considered significant.

Feel free to reach out to #apm-benchmarking-platform on Slack if you have any questions.

More details about the CI and significant changes

You can imagine this CI as a range of values that is likely to contain the true difference of means between the candidate and baseline commits.

CIs of the difference of means are often centered around 0%, because often changes are not that big:

---------------------------------(------|---^--------)-------------------------------->
                              -0.6%    0%  0.3%     +1.2%
                                 |          |        |
         lower bound of the CI --'          |        |
sample mean (center of the CI) -------------'        |
         upper bound of the CI ----------------------'

As described above, a change is considered significant if the CI is entirely outside the configured SIGNIFICANT_IMPACT_THRESHOLD (or the deprecated UNCONFIDENCE_THRESHOLD).

For instance, for an execution time metric, this confidence interval indicates a significantly worse performance:

----------------------------------------|---------|---(---------^---------)---------->
                                       0%        1%  1.3%      2.2%      3.1%
                                                  |   |         |         |
       significant impact threshold --------------'   |         |         |
                      lower bound of CI --------------'         |         |
       sample mean (center of the CI) --------------------------'         |
                      upper bound of CI ----------------------------------'

Unstable benchmarks

These benchmarks have a confidence interval too wide to call a change; treat them as noise rather than signal.

scenario:appsec-appsec-enabled-24

  • unstable execution_time [-213.878ms; +211.344ms] or [-8.021%; +7.926%]

scenario:appsec-appsec-enabled-26

  • unstable execution_time [-233.016ms; +236.501ms] or [-9.134%; +9.271%]

scenario:appsec-appsec-enabled-with-attacks-24

  • unstable execution_time [-171.640ms; +159.156ms] or [-5.556%; +5.152%]

scenario:appsec-appsec-enabled-with-attacks-26

  • unstable execution_time [-191.473ms; +194.009ms] or [-6.602%; +6.689%]

scenario:appsec-control-20

  • unstable execution_time [-123.040ms; +118.292ms] or [-7.482%; +7.193%]

scenario:appsec-control-24

  • unstable execution_time [-114.623ms; +117.590ms] or [-9.246%; +9.485%]

scenario:appsec-control-26

  • unstable execution_time [-123.730ms; +129.391ms] or [-10.000%; +10.458%]

scenario:appsec-iast-no-vulnerability-control-20

  • unstable execution_time [-14957.913µs; +13554.847µs] or [-5.927%; +5.371%]

scenario:appsec-iast-no-vulnerability-iast-enabled-default-config-20

  • unstable execution_time [-19.829ms; +14.430ms] or [-7.697%; +5.601%]

scenario:appsec-iast-with-vulnerability-iast-enabled-always-active-20

  • unstable execution_time [-24.937ms; +31.009ms] or [-4.514%; +5.613%]

scenario:child_process-shell-string-24

  • unstable execution_time [-23.239ms; +14.298ms] or [-7.072%; +4.351%]
  • unstable throughput [-131293.476op/s; +234552.266op/s] or [-3.673%; +6.562%]

scenario:debugger-line-probe-with-snapshot-default-26

  • unstable cpu_user_time [-2654.476ms; +4193.387ms] or [-27.761%; +43.856%]
  • unstable execution_time [-2795.833ms; +4337.992ms] or [-27.183%; +42.178%]
  • unstable instructions [-23.2G instructions; +36.9G instructions] or [-29.195%; +46.344%]
  • unstable max_rss_usage [-8.619MB; +12.501MB] or [-5.388%; +7.816%]
  • unstable throughput [-831.809op/s; +546.936op/s] or [-25.750%; +16.931%]

scenario:debugger-line-probe-with-snapshot-minimal-24

  • unstable cpu_user_time [-2582.684ms; +2426.038ms] or [-29.390%; +27.607%]
  • unstable execution_time [-2695.556ms; +2550.515ms] or [-28.351%; +26.825%]
  • unstable instructions [-21745.0M instructions; +20613.6M instructions] or [-30.227%; +28.654%]
  • unstable max_rss_usage [-10866.166KB; +10037.366KB] or [-6.834%; +6.313%]
  • unstable throughput [-709.983op/s; +741.935op/s] or [-20.134%; +21.040%]

scenario:debugger-line-probe-with-snapshot-minimal-26

  • unstable cpu_user_time [-3643.794ms; +5189.906ms] or [-32.840%; +46.775%]
  • unstable execution_time [-3758.200ms; +5336.741ms] or [-31.729%; +45.056%]
  • unstable instructions [-32.1G instructions; +45.7G instructions] or [-34.333%; +48.900%]
  • unstable max_rss_usage [-12.653MB; +15.589MB] or [-7.691%; +9.476%]
  • unstable throughput [-1030.128op/s; +741.777op/s] or [-35.200%; +25.347%]

scenario:debugger-line-probe-without-snapshot-24

  • unstable cpu_user_time [-1946.761ms; +3114.795ms] or [-23.527%; +37.643%]
  • unstable execution_time [-1930.422ms; +3125.845ms] or [-21.504%; +34.821%]
  • unstable instructions [-16.8G instructions; +26.7G instructions] or [-24.903%; +39.500%]
  • unstable max_rss_usage [-8.932MB; +13.225MB] or [-5.698%; +8.437%]
  • unstable throughput [-844.230op/s; +516.005op/s] or [-23.033%; +14.078%]

scenario:debugger-line-probe-without-snapshot-26

  • unstable cpu_user_time [-3.544s; +0.477s] or [-34.255%; +4.607%]
  • unstable execution_time [-3.540s; +0.487s] or [-31.985%; +4.397%]
  • unstable instructions [-31.5G instructions; +4.3G instructions] or [-36.436%; +4.912%]
  • unstable throughput [-99.655op/s; +692.828op/s] or [-3.251%; +22.601%]

scenario:dogstatsd-with-tags-20

  • unstable cpu_user_time [-343797.785µs; +345546.451µs] or [-7.169%; +7.206%]
  • unstable execution_time [-342.860ms; +348.097ms] or [-7.039%; +7.146%]
  • unstable throughput [-125618.522op/s; +120254.102op/s] or [-7.283%; +6.972%]

scenario:plugin-graphql-long-with-depth-on-max-20

  • unstable cpu_user_time [-691.529ms; +683.555ms] or [-5.392%; +5.330%]
  • unstable execution_time [-694.929ms; +688.304ms] or [-5.302%; +5.251%]
  • unstable throughput [-3.210op/s; +3.187op/s] or [-5.228%; +5.190%]

scenario:test-optimization-large-suite-20

  • unstable max_rss_usage [-5403.180KB; +6977.513KB] or [-6.600%; +8.523%]

@datadog-official

datadog-official Bot commented Jul 14, 2026

Copy link
Copy Markdown

Tests

🎉 All green!

🧪 All tests passed
❄️ No new flaky tests detected

🎯 Code Coverage (details)
Patch Coverage: 100.00%
Overall Coverage: 96.87% (+0.00%)

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 404a1fb | Docs | Datadog PR Page | Give us feedback!

@codecov

codecov Bot commented Jul 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.91%. Comparing base (4f01d4e) to head (404a1fb).
⚠️ Report is 3 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #9324   +/-   ##
=======================================
  Coverage   96.90%   96.91%           
=======================================
  Files         923      923           
  Lines      122993   122994    +1     
  Branches    21479    21385   -94     
=======================================
+ Hits       119189   119194    +5     
+ Misses       3804     3800    -4     
Flag Coverage Δ
aiguard 53.64% <ø> (-0.05%) ⬇️
aiguard-integration 57.10% <ø> (ø)
apm-bucket-0 53.87% <ø> (-0.05%) ⬇️
apm-bucket-1 58.85% <ø> (-0.05%) ⬇️
apm-bucket-2 58.08% <ø> (-0.05%) ⬇️
apm-bucket-3 55.46% <ø> (-0.05%) ⬇️
apm-capabilities-tracing 60.66% <ø> (ø)
apm-integrations-aerospike 53.02% <ø> (-0.05%) ⬇️
apm-integrations-confluentinc-kafka-javascript 57.17% <ø> (+0.01%) ⬆️
apm-integrations-couchbase 53.36% <ø> (-0.05%) ⬇️
apm-integrations-http 58.03% <ø> (-0.05%) ⬇️
apm-integrations-kafkajs 57.82% <ø> (-0.07%) ⬇️
apm-integrations-next 54.25% <ø> (-0.05%) ⬇️
apm-integrations-prisma 54.25% <ø> (-0.05%) ⬇️
appsec 68.90% <ø> (+0.01%) ⬆️
appsec-express_fastify_graphql 65.73% <ø> (-0.03%) ⬇️
appsec-integration 51.94% <100.00%> (+0.14%) ⬆️
appsec-kafka_ldapjs_lodash 59.16% <ø> (-0.04%) ⬇️
appsec-mongodb-core_mongoose_mysql 62.39% <ø> (-0.04%) ⬇️
appsec-next 52.85% <ø> (-0.05%) ⬇️
appsec-node-serialize_passport_postgres 62.03% <ø> (-0.04%) ⬇️
appsec-sourcing_stripe_template 60.42% <ø> (-0.02%) ⬇️
debugger 65.67% <ø> (-0.02%) ⬇️
instrumentations-bucket-0 48.88% <ø> (-0.05%) ⬇️
instrumentations-bucket-1 55.08% <ø> (-0.05%) ⬇️
instrumentations-bucket-10 56.70% <ø> (-0.05%) ⬇️
instrumentations-bucket-11 48.87% <ø> (-0.05%) ⬇️
instrumentations-bucket-12 49.04% <ø> (-0.05%) ⬇️
instrumentations-bucket-13 48.81% <ø> (-0.05%) ⬇️
instrumentations-bucket-2 50.01% <ø> (-0.05%) ⬇️
instrumentations-bucket-3 53.98% <ø> (-0.05%) ⬇️
instrumentations-bucket-4 49.28% <ø> (-0.05%) ⬇️
instrumentations-bucket-5 53.13% <ø> (-0.05%) ⬇️
instrumentations-bucket-6 55.72% <ø> (-0.05%) ⬇️
instrumentations-bucket-7 53.62% <ø> (-0.05%) ⬇️
instrumentations-bucket-8 54.75% <ø> (-0.05%) ⬇️
instrumentations-bucket-9 56.18% <ø> (-0.04%) ⬇️
instrumentations-instrumentation-couchbase 48.27% <ø> (-0.05%) ⬇️
instrumentations-integration-esbuild 34.05% <100.00%> (ø)
llmobs-ai_anthropic_bedrock 57.76% <ø> (-0.04%) ⬇️
llmobs-bucket-1 57.10% <ø> (-0.04%) ⬇️
llmobs-openai 57.49% <ø> (-0.04%) ⬇️
llmobs-sdk 60.06% <ø> (-0.05%) ⬇️
llmobs-vertex-ai 54.30% <ø> (-0.05%) ⬇️
master-coverage 96.91% <100.00%> (?)
openfeature 54.71% <86.95%> (-0.02%) ⬇️
openfeature-unit 49.93% <100.00%> (-0.05%) ⬇️
platform-core_esbuild_instrumentations-misc 38.51% <100.00%> (-0.05%) ⬇️
platform-integration 62.32% <ø> (ø)
platform-shimmer_unit-guardrails_webpack 37.32% <100.00%> (-0.03%) ⬇️
plugins-bucket-0 53.25% <ø> (-0.04%) ⬇️
plugins-bucket-1 55.19% <ø> (ø)
plugins-bucket-11 57.62% <ø> (-0.04%) ⬇️
plugins-bucket-18 57.15% <ø> (-0.05%) ⬇️
plugins-bucket-19 55.46% <ø> (-0.05%) ⬇️
plugins-bucket-20 57.67% <ø> (-0.05%) ⬇️
plugins-bucket-4 53.87% <ø> (-0.05%) ⬇️
plugins-bullmq_cassandra_cookie 57.46% <ø> (-0.05%) ⬇️
plugins-cookie-parser_crypto_dd-trace-api 52.41% <ø> (-0.05%) ⬇️
plugins-fetch_fs_generic-pool 54.58% <ø> (-0.05%) ⬇️
plugins-google-cloud-pubsub_grpc_handlebars 59.91% <ø> (-0.05%) ⬇️
plugins-hapi_hono_ioredis 55.85% <ø> (-0.05%) ⬇️
plugins-jest_knex_langgraph 51.78% <ø> (-0.05%) ⬇️
plugins-ldapjs_light-my-request_limitd-client 53.50% <ø> (-0.05%) ⬇️
plugins-lodash_mariadb_memcached 54.29% <ø> (-0.05%) ⬇️
plugins-moleculer_mongodb_mongodb-core 57.39% <ø> (-0.05%) ⬇️
plugins-mongoose_multer_mysql 54.78% <ø> (-0.05%) ⬇️
plugins-mysql2_nats_node-serialize 56.32% <ø> (-0.05%) ⬇️
plugins-opensearch_passport-http_pino 55.18% <ø> (-0.05%) ⬇️
plugins-postgres_process_pug 54.37% <ø> (-0.05%) ⬇️
plugins-redis_router_sequelize 57.15% <ø> (-0.08%) ⬇️
plugins-test-and-upstream-rhea_undici_url 57.05% <ø> (-0.05%) ⬇️
plugins-valkey_vm_winston 53.93% <ø> (-0.13%) ⬇️
plugins-ws 54.92% <ø> (-0.05%) ⬇️
profiling 58.25% <ø> (-0.04%) ⬇️
serverless-aws-sdk-aws-sdk 50.75% <ø> (-0.04%) ⬇️
serverless-aws-sdk-bedrockruntime 50.74% <ø> (-0.05%) ⬇️
serverless-aws-sdk-client 52.08% <ø> (-0.05%) ⬇️
serverless-aws-sdk-dynamodb 51.79% <ø> (-0.05%) ⬇️
serverless-aws-sdk-eventbridge 46.44% <ø> (-0.05%) ⬇️
serverless-aws-sdk-kinesis 54.78% <ø> (-0.05%) ⬇️
serverless-aws-sdk-lambda 52.86% <ø> (-0.05%) ⬇️
serverless-aws-sdk-s3 51.58% <ø> (-0.05%) ⬇️
serverless-aws-sdk-serverless-peer-service 54.81% <ø> (-0.05%) ⬇️
serverless-aws-sdk-sns 55.53% <ø> (-0.05%) ⬇️
serverless-aws-sdk-sqs 55.95% <ø> (-0.05%) ⬇️
serverless-aws-sdk-stepfunctions 51.35% <ø> (-0.05%) ⬇️
serverless-aws-sdk-util 48.53% <ø> (-0.05%) ⬇️
serverless-azure-functions-servicebus_lambda ?
serverless-bucket-0 55.23% <ø> (+0.30%) ⬆️
serverless-bucket-1 56.05% <ø> (?)
test-optimization-cucumber 73.04% <ø> (+0.08%) ⬆️
test-optimization-cypress 66.37% <ø> (+0.05%) ⬆️
test-optimization-jest 74.37% <ø> (-0.03%) ⬇️
test-optimization-mocha 74.73% <ø> (+0.05%) ⬆️
test-optimization-playwright-playwright-atr 61.44% <ø> (+0.02%) ⬆️
test-optimization-playwright-playwright-efd 61.63% <ø> (+0.03%) ⬆️
test-optimization-playwright-playwright-final-status 61.60% <ø> (+0.09%) ⬆️
test-optimization-playwright-playwright-impacted-tests 61.32% <ø> (+0.19%) ⬆️
test-optimization-playwright-playwright-reporting 61.21% <ø> (+0.02%) ⬆️
test-optimization-playwright-playwright-test-management 62.17% <ø> (+0.21%) ⬆️
test-optimization-playwright-playwright-test-span 61.35% <ø> (-0.03%) ⬇️
test-optimization-selenium 60.74% <ø> (-0.14%) ⬇️
test-optimization-testopt 59.23% <ø> (+0.08%) ⬆️
test-optimization-vitest 71.30% <ø> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@BridgeAR
BridgeAR marked this pull request as ready for review July 14, 2026 20:08
@BridgeAR
BridgeAR requested review from a team as code owners July 14, 2026 20:08
@BridgeAR
BridgeAR requested review from leoromanovsky, pavlokhrebto and tlhunter and removed request for a team July 14, 2026 20:08

@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: 2c07b16731

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/dd-trace/src/openfeature/require-provider.js Outdated
@BridgeAR
BridgeAR force-pushed the BridgeAR/2026-07-14-fix-openfeature-nft branch from 2c07b16 to 3a9d4b5 Compare July 14, 2026 21:33
@leoromanovsky
leoromanovsky requested a review from greghuels July 14, 2026 21:35
@BridgeAR
BridgeAR marked this pull request as draft July 14, 2026 21:36
@BridgeAR
BridgeAR marked this pull request as ready for review July 15, 2026 00:21

@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: 96b851aad3

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread packages/dd-trace/src/openfeature/require-provider.js
Comment thread README.md Outdated
tlhunter
tlhunter previously approved these changes Jul 15, 2026
BridgeAR and others added 5 commits July 15, 2026 19:16
Next.js standalone builds using pnpm omitted the OpenFeature provider because the shared optional-peer wrapper was invisible to nft, leaving tracer.openfeature as the no-op provider at runtime. Keep the bundler escape hatch while exposing a file-traceable fallback entrypoint for tools that cannot recognize the wrapper.

Refs: #8635
Webpack parses a bare dynamic require even behind the non-webpack branch, reintroducing a critical expression-dependency warning when the peer is absent. The fallback must remain recognizable to nft without exposing that expression dependency to webpack.
Moving the provider call inside the createRequire fallback left webpack's runtime on `__non_webpack_require__`, so relocated bundles could not find the installed peer and silently selected NoopFlaggingProvider. Keep the final load at the rewrite site while preserving nft's createRequire binding.
Node's ESM resolver does not append `.js` to package subpaths without an exports map, so the extensionless fallback fails before file tracing starts. Pin both the ESM import and automatic nft discovery from the default entrypoint.
@BridgeAR
BridgeAR force-pushed the BridgeAR/2026-07-14-fix-openfeature-nft branch from 96b851a to 78bff46 Compare July 15, 2026 17:18
@BridgeAR
BridgeAR marked this pull request as draft July 15, 2026 17:20
Node 18 and 20 require the `.js` suffix for ESM package subpaths, while CommonJS resolves the extensionless form. The full-root nft assertion exceeded Mocha's timeout under coverage; the runtime-wrapper trace keeps the automatic nft contract pinned without tracing the whole package again.
@BridgeAR
BridgeAR marked this pull request as ready for review July 16, 2026 00:22
@BridgeAR
BridgeAR merged commit 8339a6f into master Jul 16, 2026
659 checks passed
@BridgeAR
BridgeAR deleted the BridgeAR/2026-07-14-fix-openfeature-nft branch July 16, 2026 19:08
leoromanovsky pushed a commit that referenced this pull request Jul 22, 2026
Next.js standalone builds using pnpm omitted the OpenFeature provider because the shared optional-peer wrapper was invisible to nft, leaving tracer.openfeature as the no-op provider at runtime. Keep the bundler escape hatch while exposing a file-traceable fallback entrypoint for tools that cannot recognize the wrapper.
Also document CommonJS and ESM entrypoints.

Fixes: #8635
leoromanovsky pushed a commit that referenced this pull request Jul 22, 2026
Next.js standalone builds using pnpm omitted the OpenFeature provider because the shared optional-peer wrapper was invisible to nft, leaving tracer.openfeature as the no-op provider at runtime. Keep the bundler escape hatch while exposing a file-traceable fallback entrypoint for tools that cannot recognize the wrapper.
Also document CommonJS and ESM entrypoints.

Fixes: #8635
rochdev added a commit that referenced this pull request Aug 1, 2026
…point

dd-trace/openfeature previously only existed as a side-effect require for
file tracers (#9324). Turn it into the real public entrypoint: it now
returns a usable FlaggingProvider instance after tracer.init(), and
tracer.openfeature is deprecated in its favor since it doesn't work in
bundled applications.

Extract the base provider class into a factory so it can be constructed
from either the bundler-opaque require-provider wrapper (legacy
tracer.openfeature) or a plain require (the new entrypoint) without
duplicating the class body.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
rochdev added a commit that referenced this pull request Aug 10, 2026
…point

dd-trace/openfeature previously only existed as a side-effect require for
file tracers (#9324). Turn it into the real public entrypoint: it now
returns a usable FlaggingProvider instance after tracer.init(), and
tracer.openfeature is deprecated in its favor since it doesn't work in
bundled applications.

Extract the base provider class into a factory so it can be constructed
from either the bundler-opaque require-provider wrapper (legacy
tracer.openfeature) or a plain require (the new entrypoint) without
duplicating the class body.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
rochdev added a commit that referenced this pull request Aug 13, 2026
…point

dd-trace/openfeature previously only existed as a side-effect require for
file tracers (#9324). Turn it into the real public entrypoint: it now
returns a usable FlaggingProvider instance after tracer.init(), and
tracer.openfeature is deprecated in its favor since it doesn't work in
bundled applications.

Extract the base provider class into a factory so it can be constructed
from either the bundler-opaque require-provider wrapper (legacy
tracer.openfeature) or a plain require (the new entrypoint) without
duplicating the class body.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
rochdev added a commit that referenced this pull request Aug 13, 2026
…l peer dependency (#9570)

* feat(openfeature): return a ready provider from the openfeature entrypoint

dd-trace/openfeature previously only existed as a side-effect require for
file tracers (#9324). Turn it into the real public entrypoint: it now
returns a usable FlaggingProvider instance after tracer.init(), and
tracer.openfeature is deprecated in its favor since it doesn't work in
bundled applications.

Extract the base provider class into a factory so it can be constructed
from either the bundler-opaque require-provider wrapper (legacy
tracer.openfeature) or a plain require (the new entrypoint) without
duplicating the class body.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(openfeature): raise nft trace timeout for the entrypoint test

openfeature.js now pulls in the full tracer package to check
tracer.init() state, so nodeFileTrace has a much larger dependency
tree to walk. The default 5s mocha timeout was tight enough that CI
runners under load exceeded it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(openfeature): vendor the flagging provider instead of an optional peer

`@datadog/openfeature-node-server` was an optional peer dependency resolved
through a bundler-opaque require, requiring dedicated esbuild/webpack plugin
code to keep the require invisible when the peer wasn't installed (#8635) and
to inline it so bundles survived relocation when it was (#8980). Vendoring the
provider into `vendor/dist/` removes the need for a peer at all, so all of
that machinery (`feature-registry.js`, `register.js`, `require-provider.js`,
the optional-peer esbuild/webpack loaders, and their integration tests) is
deleted in favor of a single lazy `tracer.openfeature` property.

The vendored provider's only remaining external dependency is
`@openfeature/server-sdk`, used solely for `OpenFeatureEventEmitter` and
`ProviderEvents`. Bundling our own copy would give those a different identity
than the customer's, so it's externalized to a small bridge module
(`server-sdk-bridge.js`) that a new `openfeature-server-sdk` instrumentation
fills in from the customer's own `require()`.

`FlaggingProvider#initialize` also unrefs the vendored provider's
initialization timer, which otherwise keeps an idle process (a short script, a
serverless handler) alive for up to `initializationTimeoutMs` while waiting
for configuration to arrive. TODO left to remove this once
`@datadog/openfeature-node-server` unrefs it upstream.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(build): exclude unresolved peer entries from license check

scripts/check_licenses.js treated every non-dev entry in
vendor/package-lock.json as requiring license attribution, including
`peer: true` entries. Those record an unresolved peer dependency range
that npm never actually installs, so nothing is shipped for them. The
official dd-license-attribution tool used in CI already excludes these,
so the local script disagreed with CI and had two extraneous rows
(@openfeature/core, @openfeature/server-sdk) added to satisfy it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(licenses): stop expecting npm peer dependencies to need attribution

The prior fix's comment claimed npm never installs peer entries, which is
false under npm 7+ auto-install-peers - vendor/node_modules physically has
@openfeature/core and @openfeature/server-sdk installed. The real reason
they don't need attribution is that peer dependencies are supplied by the
consumer rather than shipped by this package, matching how the yarn.lock
walk already excludes peerDependencies. The pre-existing vendor-peer test
fixture assumed the opposite and was never validated against real CI
behavior for a peer case, so it broke once the npm-lock scan started
excluding peers too.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): implement full ProviderEventEmitter contract in the deferred bridge emitter

@openfeature/core's transferListeners always calls oldProvider.events?.removeHandler(...)
on every subsequent OpenFeature.setProvider() call for a domain, regardless of whether the
app registered any handlers itself. The deferred emitter only implemented addHandler/emit,
so replacing the Datadog OpenFeature provider with another provider at runtime threw
"oldProvider.events.removeHandler is not a function", crashing the customer's app.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): address review feedback on tests and SSI scope

- Fix test:openfeature script so the instrumentation spec actually runs:
  mocha treats a brace-only glob segment as a literal filename, so add
  a wildcard segment that both mocha and verify-exercised-tests resolve.
- Add real esbuild/webpack black-box tests that bundle
  @openfeature/server-sdk (not marked external) and assert dd-trace's
  bundler-instrumentation mechanism still bridges the real event
  emitter into the vendored provider.
- Correct comments in proxy.js and the dd-trace-api plugin: SSI itself
  is fixed by this PR's vendoring; the only remaining gap is that the
  dd-trace-api shim has no openfeature handoff.

Generated with Claude Code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(openfeature): drop the server-sdk event-emitter bridge

@datadog/openfeature-node-server 2.1.0 ships its own ProviderEventEmitter
and no longer depends on @openfeature/server-sdk at all (neither as a
dependency nor a peer), so the identity-preserving bridge this PR
introduced is no longer needed:

- Bump @datadog/openfeature-node-server to 2.1.0 everywhere it's pinned
  (vendor, root devDependencies, plugin versions matrix) and rebuild
  vendor/dist.
- Remove the @openfeature/server-sdk external redirect from
  vendor/rspack.config.js -- the vendored provider no longer references
  that package at all.
- Delete server-sdk-bridge.js, the openfeature-server-sdk require-hook
  instrumentation, and their specs.
- Remove the now-obsolete esbuild/webpack black-box tests that verified
  the bridge survived bundling -- there's no bridge left to verify.
- Update file-tracing.spec.js's expected traced files and loaded-modules
  list to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): update stale yarn.lock entry for openfeature-node-server

root package.json's devDependency was bumped to 2.1.0 but yarn.lock still
pinned 2.0.2, which made bun's yarn.lock-migration fail to resolve the
package in plugin test CI.

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
dd-octo-sts Bot pushed a commit that referenced this pull request Aug 13, 2026
…l peer dependency (#9570)

* feat(openfeature): return a ready provider from the openfeature entrypoint

dd-trace/openfeature previously only existed as a side-effect require for
file tracers (#9324). Turn it into the real public entrypoint: it now
returns a usable FlaggingProvider instance after tracer.init(), and
tracer.openfeature is deprecated in its favor since it doesn't work in
bundled applications.

Extract the base provider class into a factory so it can be constructed
from either the bundler-opaque require-provider wrapper (legacy
tracer.openfeature) or a plain require (the new entrypoint) without
duplicating the class body.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(openfeature): raise nft trace timeout for the entrypoint test

openfeature.js now pulls in the full tracer package to check
tracer.init() state, so nodeFileTrace has a much larger dependency
tree to walk. The default 5s mocha timeout was tight enough that CI
runners under load exceeded it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(openfeature): vendor the flagging provider instead of an optional peer

`@datadog/openfeature-node-server` was an optional peer dependency resolved
through a bundler-opaque require, requiring dedicated esbuild/webpack plugin
code to keep the require invisible when the peer wasn't installed (#8635) and
to inline it so bundles survived relocation when it was (#8980). Vendoring the
provider into `vendor/dist/` removes the need for a peer at all, so all of
that machinery (`feature-registry.js`, `register.js`, `require-provider.js`,
the optional-peer esbuild/webpack loaders, and their integration tests) is
deleted in favor of a single lazy `tracer.openfeature` property.

The vendored provider's only remaining external dependency is
`@openfeature/server-sdk`, used solely for `OpenFeatureEventEmitter` and
`ProviderEvents`. Bundling our own copy would give those a different identity
than the customer's, so it's externalized to a small bridge module
(`server-sdk-bridge.js`) that a new `openfeature-server-sdk` instrumentation
fills in from the customer's own `require()`.

`FlaggingProvider#initialize` also unrefs the vendored provider's
initialization timer, which otherwise keeps an idle process (a short script, a
serverless handler) alive for up to `initializationTimeoutMs` while waiting
for configuration to arrive. TODO left to remove this once
`@datadog/openfeature-node-server` unrefs it upstream.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(build): exclude unresolved peer entries from license check

scripts/check_licenses.js treated every non-dev entry in
vendor/package-lock.json as requiring license attribution, including
`peer: true` entries. Those record an unresolved peer dependency range
that npm never actually installs, so nothing is shipped for them. The
official dd-license-attribution tool used in CI already excludes these,
so the local script disagreed with CI and had two extraneous rows
(@openfeature/core, @openfeature/server-sdk) added to satisfy it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(licenses): stop expecting npm peer dependencies to need attribution

The prior fix's comment claimed npm never installs peer entries, which is
false under npm 7+ auto-install-peers - vendor/node_modules physically has
@openfeature/core and @openfeature/server-sdk installed. The real reason
they don't need attribution is that peer dependencies are supplied by the
consumer rather than shipped by this package, matching how the yarn.lock
walk already excludes peerDependencies. The pre-existing vendor-peer test
fixture assumed the opposite and was never validated against real CI
behavior for a peer case, so it broke once the npm-lock scan started
excluding peers too.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): implement full ProviderEventEmitter contract in the deferred bridge emitter

@openfeature/core's transferListeners always calls oldProvider.events?.removeHandler(...)
on every subsequent OpenFeature.setProvider() call for a domain, regardless of whether the
app registered any handlers itself. The deferred emitter only implemented addHandler/emit,
so replacing the Datadog OpenFeature provider with another provider at runtime threw
"oldProvider.events.removeHandler is not a function", crashing the customer's app.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): address review feedback on tests and SSI scope

- Fix test:openfeature script so the instrumentation spec actually runs:
  mocha treats a brace-only glob segment as a literal filename, so add
  a wildcard segment that both mocha and verify-exercised-tests resolve.
- Add real esbuild/webpack black-box tests that bundle
  @openfeature/server-sdk (not marked external) and assert dd-trace's
  bundler-instrumentation mechanism still bridges the real event
  emitter into the vendored provider.
- Correct comments in proxy.js and the dd-trace-api plugin: SSI itself
  is fixed by this PR's vendoring; the only remaining gap is that the
  dd-trace-api shim has no openfeature handoff.

Generated with Claude Code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(openfeature): drop the server-sdk event-emitter bridge

@datadog/openfeature-node-server 2.1.0 ships its own ProviderEventEmitter
and no longer depends on @openfeature/server-sdk at all (neither as a
dependency nor a peer), so the identity-preserving bridge this PR
introduced is no longer needed:

- Bump @datadog/openfeature-node-server to 2.1.0 everywhere it's pinned
  (vendor, root devDependencies, plugin versions matrix) and rebuild
  vendor/dist.
- Remove the @openfeature/server-sdk external redirect from
  vendor/rspack.config.js -- the vendored provider no longer references
  that package at all.
- Delete server-sdk-bridge.js, the openfeature-server-sdk require-hook
  instrumentation, and their specs.
- Remove the now-obsolete esbuild/webpack black-box tests that verified
  the bridge survived bundling -- there's no bridge left to verify.
- Update file-tracing.spec.js's expected traced files and loaded-modules
  list to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): update stale yarn.lock entry for openfeature-node-server

root package.json's devDependency was bumped to 2.1.0 but yarn.lock still
pinned 2.0.2, which made bun's yarn.lock-migration fail to resolve the
package in plugin test CI.

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
dd-octo-sts Bot pushed a commit that referenced this pull request Aug 13, 2026
…l peer dependency (#9570)

* feat(openfeature): return a ready provider from the openfeature entrypoint

dd-trace/openfeature previously only existed as a side-effect require for
file tracers (#9324). Turn it into the real public entrypoint: it now
returns a usable FlaggingProvider instance after tracer.init(), and
tracer.openfeature is deprecated in its favor since it doesn't work in
bundled applications.

Extract the base provider class into a factory so it can be constructed
from either the bundler-opaque require-provider wrapper (legacy
tracer.openfeature) or a plain require (the new entrypoint) without
duplicating the class body.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(openfeature): raise nft trace timeout for the entrypoint test

openfeature.js now pulls in the full tracer package to check
tracer.init() state, so nodeFileTrace has a much larger dependency
tree to walk. The default 5s mocha timeout was tight enough that CI
runners under load exceeded it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(openfeature): vendor the flagging provider instead of an optional peer

`@datadog/openfeature-node-server` was an optional peer dependency resolved
through a bundler-opaque require, requiring dedicated esbuild/webpack plugin
code to keep the require invisible when the peer wasn't installed (#8635) and
to inline it so bundles survived relocation when it was (#8980). Vendoring the
provider into `vendor/dist/` removes the need for a peer at all, so all of
that machinery (`feature-registry.js`, `register.js`, `require-provider.js`,
the optional-peer esbuild/webpack loaders, and their integration tests) is
deleted in favor of a single lazy `tracer.openfeature` property.

The vendored provider's only remaining external dependency is
`@openfeature/server-sdk`, used solely for `OpenFeatureEventEmitter` and
`ProviderEvents`. Bundling our own copy would give those a different identity
than the customer's, so it's externalized to a small bridge module
(`server-sdk-bridge.js`) that a new `openfeature-server-sdk` instrumentation
fills in from the customer's own `require()`.

`FlaggingProvider#initialize` also unrefs the vendored provider's
initialization timer, which otherwise keeps an idle process (a short script, a
serverless handler) alive for up to `initializationTimeoutMs` while waiting
for configuration to arrive. TODO left to remove this once
`@datadog/openfeature-node-server` unrefs it upstream.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(build): exclude unresolved peer entries from license check

scripts/check_licenses.js treated every non-dev entry in
vendor/package-lock.json as requiring license attribution, including
`peer: true` entries. Those record an unresolved peer dependency range
that npm never actually installs, so nothing is shipped for them. The
official dd-license-attribution tool used in CI already excludes these,
so the local script disagreed with CI and had two extraneous rows
(@openfeature/core, @openfeature/server-sdk) added to satisfy it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(licenses): stop expecting npm peer dependencies to need attribution

The prior fix's comment claimed npm never installs peer entries, which is
false under npm 7+ auto-install-peers - vendor/node_modules physically has
@openfeature/core and @openfeature/server-sdk installed. The real reason
they don't need attribution is that peer dependencies are supplied by the
consumer rather than shipped by this package, matching how the yarn.lock
walk already excludes peerDependencies. The pre-existing vendor-peer test
fixture assumed the opposite and was never validated against real CI
behavior for a peer case, so it broke once the npm-lock scan started
excluding peers too.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): implement full ProviderEventEmitter contract in the deferred bridge emitter

@openfeature/core's transferListeners always calls oldProvider.events?.removeHandler(...)
on every subsequent OpenFeature.setProvider() call for a domain, regardless of whether the
app registered any handlers itself. The deferred emitter only implemented addHandler/emit,
so replacing the Datadog OpenFeature provider with another provider at runtime threw
"oldProvider.events.removeHandler is not a function", crashing the customer's app.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): address review feedback on tests and SSI scope

- Fix test:openfeature script so the instrumentation spec actually runs:
  mocha treats a brace-only glob segment as a literal filename, so add
  a wildcard segment that both mocha and verify-exercised-tests resolve.
- Add real esbuild/webpack black-box tests that bundle
  @openfeature/server-sdk (not marked external) and assert dd-trace's
  bundler-instrumentation mechanism still bridges the real event
  emitter into the vendored provider.
- Correct comments in proxy.js and the dd-trace-api plugin: SSI itself
  is fixed by this PR's vendoring; the only remaining gap is that the
  dd-trace-api shim has no openfeature handoff.

Generated with Claude Code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(openfeature): drop the server-sdk event-emitter bridge

@datadog/openfeature-node-server 2.1.0 ships its own ProviderEventEmitter
and no longer depends on @openfeature/server-sdk at all (neither as a
dependency nor a peer), so the identity-preserving bridge this PR
introduced is no longer needed:

- Bump @datadog/openfeature-node-server to 2.1.0 everywhere it's pinned
  (vendor, root devDependencies, plugin versions matrix) and rebuild
  vendor/dist.
- Remove the @openfeature/server-sdk external redirect from
  vendor/rspack.config.js -- the vendored provider no longer references
  that package at all.
- Delete server-sdk-bridge.js, the openfeature-server-sdk require-hook
  instrumentation, and their specs.
- Remove the now-obsolete esbuild/webpack black-box tests that verified
  the bridge survived bundling -- there's no bridge left to verify.
- Update file-tracing.spec.js's expected traced files and loaded-modules
  list to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): update stale yarn.lock entry for openfeature-node-server

root package.json's devDependency was bumped to 2.1.0 but yarn.lock still
pinned 2.0.2, which made bun's yarn.lock-migration fail to resolve the
package in plugin test CI.

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
pabloerhard pushed a commit that referenced this pull request Aug 17, 2026
…l peer dependency (#9570)

* feat(openfeature): return a ready provider from the openfeature entrypoint

dd-trace/openfeature previously only existed as a side-effect require for
file tracers (#9324). Turn it into the real public entrypoint: it now
returns a usable FlaggingProvider instance after tracer.init(), and
tracer.openfeature is deprecated in its favor since it doesn't work in
bundled applications.

Extract the base provider class into a factory so it can be constructed
from either the bundler-opaque require-provider wrapper (legacy
tracer.openfeature) or a plain require (the new entrypoint) without
duplicating the class body.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(openfeature): raise nft trace timeout for the entrypoint test

openfeature.js now pulls in the full tracer package to check
tracer.init() state, so nodeFileTrace has a much larger dependency
tree to walk. The default 5s mocha timeout was tight enough that CI
runners under load exceeded it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(openfeature): vendor the flagging provider instead of an optional peer

`@datadog/openfeature-node-server` was an optional peer dependency resolved
through a bundler-opaque require, requiring dedicated esbuild/webpack plugin
code to keep the require invisible when the peer wasn't installed (#8635) and
to inline it so bundles survived relocation when it was (#8980). Vendoring the
provider into `vendor/dist/` removes the need for a peer at all, so all of
that machinery (`feature-registry.js`, `register.js`, `require-provider.js`,
the optional-peer esbuild/webpack loaders, and their integration tests) is
deleted in favor of a single lazy `tracer.openfeature` property.

The vendored provider's only remaining external dependency is
`@openfeature/server-sdk`, used solely for `OpenFeatureEventEmitter` and
`ProviderEvents`. Bundling our own copy would give those a different identity
than the customer's, so it's externalized to a small bridge module
(`server-sdk-bridge.js`) that a new `openfeature-server-sdk` instrumentation
fills in from the customer's own `require()`.

`FlaggingProvider#initialize` also unrefs the vendored provider's
initialization timer, which otherwise keeps an idle process (a short script, a
serverless handler) alive for up to `initializationTimeoutMs` while waiting
for configuration to arrive. TODO left to remove this once
`@datadog/openfeature-node-server` unrefs it upstream.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(build): exclude unresolved peer entries from license check

scripts/check_licenses.js treated every non-dev entry in
vendor/package-lock.json as requiring license attribution, including
`peer: true` entries. Those record an unresolved peer dependency range
that npm never actually installs, so nothing is shipped for them. The
official dd-license-attribution tool used in CI already excludes these,
so the local script disagreed with CI and had two extraneous rows
(@openfeature/core, @openfeature/server-sdk) added to satisfy it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(licenses): stop expecting npm peer dependencies to need attribution

The prior fix's comment claimed npm never installs peer entries, which is
false under npm 7+ auto-install-peers - vendor/node_modules physically has
@openfeature/core and @openfeature/server-sdk installed. The real reason
they don't need attribution is that peer dependencies are supplied by the
consumer rather than shipped by this package, matching how the yarn.lock
walk already excludes peerDependencies. The pre-existing vendor-peer test
fixture assumed the opposite and was never validated against real CI
behavior for a peer case, so it broke once the npm-lock scan started
excluding peers too.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): implement full ProviderEventEmitter contract in the deferred bridge emitter

@openfeature/core's transferListeners always calls oldProvider.events?.removeHandler(...)
on every subsequent OpenFeature.setProvider() call for a domain, regardless of whether the
app registered any handlers itself. The deferred emitter only implemented addHandler/emit,
so replacing the Datadog OpenFeature provider with another provider at runtime threw
"oldProvider.events.removeHandler is not a function", crashing the customer's app.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): address review feedback on tests and SSI scope

- Fix test:openfeature script so the instrumentation spec actually runs:
  mocha treats a brace-only glob segment as a literal filename, so add
  a wildcard segment that both mocha and verify-exercised-tests resolve.
- Add real esbuild/webpack black-box tests that bundle
  @openfeature/server-sdk (not marked external) and assert dd-trace's
  bundler-instrumentation mechanism still bridges the real event
  emitter into the vendored provider.
- Correct comments in proxy.js and the dd-trace-api plugin: SSI itself
  is fixed by this PR's vendoring; the only remaining gap is that the
  dd-trace-api shim has no openfeature handoff.

Generated with Claude Code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(openfeature): drop the server-sdk event-emitter bridge

@datadog/openfeature-node-server 2.1.0 ships its own ProviderEventEmitter
and no longer depends on @openfeature/server-sdk at all (neither as a
dependency nor a peer), so the identity-preserving bridge this PR
introduced is no longer needed:

- Bump @datadog/openfeature-node-server to 2.1.0 everywhere it's pinned
  (vendor, root devDependencies, plugin versions matrix) and rebuild
  vendor/dist.
- Remove the @openfeature/server-sdk external redirect from
  vendor/rspack.config.js -- the vendored provider no longer references
  that package at all.
- Delete server-sdk-bridge.js, the openfeature-server-sdk require-hook
  instrumentation, and their specs.
- Remove the now-obsolete esbuild/webpack black-box tests that verified
  the bridge survived bundling -- there's no bridge left to verify.
- Update file-tracing.spec.js's expected traced files and loaded-modules
  list to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): update stale yarn.lock entry for openfeature-node-server

root package.json's devDependency was bumped to 2.1.0 but yarn.lock still
pinned 2.0.2, which made bun's yarn.lock-migration fail to resolve the
package in plugin test CI.

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
pabloerhard pushed a commit that referenced this pull request Aug 17, 2026
…l peer dependency (#9570)

* feat(openfeature): return a ready provider from the openfeature entrypoint

dd-trace/openfeature previously only existed as a side-effect require for
file tracers (#9324). Turn it into the real public entrypoint: it now
returns a usable FlaggingProvider instance after tracer.init(), and
tracer.openfeature is deprecated in its favor since it doesn't work in
bundled applications.

Extract the base provider class into a factory so it can be constructed
from either the bundler-opaque require-provider wrapper (legacy
tracer.openfeature) or a plain require (the new entrypoint) without
duplicating the class body.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(openfeature): raise nft trace timeout for the entrypoint test

openfeature.js now pulls in the full tracer package to check
tracer.init() state, so nodeFileTrace has a much larger dependency
tree to walk. The default 5s mocha timeout was tight enough that CI
runners under load exceeded it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(openfeature): vendor the flagging provider instead of an optional peer

`@datadog/openfeature-node-server` was an optional peer dependency resolved
through a bundler-opaque require, requiring dedicated esbuild/webpack plugin
code to keep the require invisible when the peer wasn't installed (#8635) and
to inline it so bundles survived relocation when it was (#8980). Vendoring the
provider into `vendor/dist/` removes the need for a peer at all, so all of
that machinery (`feature-registry.js`, `register.js`, `require-provider.js`,
the optional-peer esbuild/webpack loaders, and their integration tests) is
deleted in favor of a single lazy `tracer.openfeature` property.

The vendored provider's only remaining external dependency is
`@openfeature/server-sdk`, used solely for `OpenFeatureEventEmitter` and
`ProviderEvents`. Bundling our own copy would give those a different identity
than the customer's, so it's externalized to a small bridge module
(`server-sdk-bridge.js`) that a new `openfeature-server-sdk` instrumentation
fills in from the customer's own `require()`.

`FlaggingProvider#initialize` also unrefs the vendored provider's
initialization timer, which otherwise keeps an idle process (a short script, a
serverless handler) alive for up to `initializationTimeoutMs` while waiting
for configuration to arrive. TODO left to remove this once
`@datadog/openfeature-node-server` unrefs it upstream.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(build): exclude unresolved peer entries from license check

scripts/check_licenses.js treated every non-dev entry in
vendor/package-lock.json as requiring license attribution, including
`peer: true` entries. Those record an unresolved peer dependency range
that npm never actually installs, so nothing is shipped for them. The
official dd-license-attribution tool used in CI already excludes these,
so the local script disagreed with CI and had two extraneous rows
(@openfeature/core, @openfeature/server-sdk) added to satisfy it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* test(licenses): stop expecting npm peer dependencies to need attribution

The prior fix's comment claimed npm never installs peer entries, which is
false under npm 7+ auto-install-peers - vendor/node_modules physically has
@openfeature/core and @openfeature/server-sdk installed. The real reason
they don't need attribution is that peer dependencies are supplied by the
consumer rather than shipped by this package, matching how the yarn.lock
walk already excludes peerDependencies. The pre-existing vendor-peer test
fixture assumed the opposite and was never validated against real CI
behavior for a peer case, so it broke once the npm-lock scan started
excluding peers too.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): implement full ProviderEventEmitter contract in the deferred bridge emitter

@openfeature/core's transferListeners always calls oldProvider.events?.removeHandler(...)
on every subsequent OpenFeature.setProvider() call for a domain, regardless of whether the
app registered any handlers itself. The deferred emitter only implemented addHandler/emit,
so replacing the Datadog OpenFeature provider with another provider at runtime threw
"oldProvider.events.removeHandler is not a function", crashing the customer's app.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): address review feedback on tests and SSI scope

- Fix test:openfeature script so the instrumentation spec actually runs:
  mocha treats a brace-only glob segment as a literal filename, so add
  a wildcard segment that both mocha and verify-exercised-tests resolve.
- Add real esbuild/webpack black-box tests that bundle
  @openfeature/server-sdk (not marked external) and assert dd-trace's
  bundler-instrumentation mechanism still bridges the real event
  emitter into the vendored provider.
- Correct comments in proxy.js and the dd-trace-api plugin: SSI itself
  is fixed by this PR's vendoring; the only remaining gap is that the
  dd-trace-api shim has no openfeature handoff.

Generated with Claude Code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(openfeature): drop the server-sdk event-emitter bridge

@datadog/openfeature-node-server 2.1.0 ships its own ProviderEventEmitter
and no longer depends on @openfeature/server-sdk at all (neither as a
dependency nor a peer), so the identity-preserving bridge this PR
introduced is no longer needed:

- Bump @datadog/openfeature-node-server to 2.1.0 everywhere it's pinned
  (vendor, root devDependencies, plugin versions matrix) and rebuild
  vendor/dist.
- Remove the @openfeature/server-sdk external redirect from
  vendor/rspack.config.js -- the vendored provider no longer references
  that package at all.
- Delete server-sdk-bridge.js, the openfeature-server-sdk require-hook
  instrumentation, and their specs.
- Remove the now-obsolete esbuild/webpack black-box tests that verified
  the bridge survived bundling -- there's no bridge left to verify.
- Update file-tracing.spec.js's expected traced files and loaded-modules
  list to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(openfeature): update stale yarn.lock entry for openfeature-node-server

root package.json's devDependency was bumped to 2.1.0 but yarn.lock still
pinned 2.0.2, which made bun's yarn.lock-migration fail to resolve the
package in plugin test CI.

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants