fix(openfeature): support custom agentless endpoints#9468
fix(openfeature): support custom agentless endpoints#9468leoromanovsky wants to merge 3 commits into
Conversation
Overall package sizeSelf size: 7.51 MB Dependency sizes| name | version | self size | total size | |------|---------|-----------|------------| | import-in-the-middle | 3.3.2 | 124.41 kB | 440.65 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 |
|
BenchmarksBenchmark execution time: 2026-07-21 23:45:45 Comparing candidate commit 6ee9987 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 2313 metrics, 45 unstable metrics.
|
Motivation
DataDog/system-tests#7355 enables the Node.js Feature Flagging configuration-source contract starting with 6.5.0. That contract exposed three concrete behaviors missing from Node.js.
The earlier local system-test pass was real; the later failure came from a change to the dd-trace-js branch between the two runs:
51756483a265and dd-trace-js94a16dc3017b. Node.js was manually ungated in the manifest, and the FFE suite completed with 53 passed and 18 existing XPASS cases; all 29 configuration-source tests passed.94a16dcexplicitly treatedhost.docker.internalas a controlled local target. The system-test mock backend was therefore reachable over HTTP from the library container and received the API key.30338367a818. Itsdcdc37f52275commit replaced the controlled-host exception with a loopback-only HTTPS guard. The same Docker fixture is addressed ashttp://host.docker.internal:<port>, which is not loopback inside the container, so Node.js threwFeature Flagging agentless URL must use HTTPS unless it targets loopbackbefore making the request.Docker makes the distinction observable because the host-side mock server cannot be addressed as container loopback. It was not an intermittent Docker failure and the earlier test was not skipped; the regression was introduced by the loopback-only guard after the green SHA.
http://host.docker.internal:<port>UFC endpoint, requires an authenticated request to the canonical config path, evaluates the delivered flag, and verifies that Remote Configuration was not selected. Node.js rejected that explicit non-loopback HTTP URL before making the request. This also blocked local laptop development and the dogfooding app when it points at a local proxy.invalidor reservedoffline, then requires zero agentless requests and no FFE Remote Configuration capability or product. Node.js allowed invalid input to fall back to the default agentless path instead of throwing before any delivery path was selected.Local Docker reproduction on the current fixed head
The current PR head was tested against the current system-tests PR head through the real PARAMETRIC Docker topology:
The image was freshly built with the standard system-tests command:
The same freshly built image was then run sequentially to remove unrelated local high-worker test-agent port-routing noise:
The final JUnit and JSON reports agree:
Selected JUnit cases proving the missing Node.js behaviors now pass:
Those cases assert the behavior, not merely process liveness:
offlinesources produced zero agentless requests and no FFE Remote Configuration capability or product after provider access.The container logs include the expected runtime and failure-path signals:
The code mounted into the library container was byte-identical to the current PR checkout:
This reproduces the system-tests Dockerfile, library container, test-agent topology, and
host.docker.internalboundary locally. The local Docker engine is arm64; GitHub's Linux runner is amd64.These are delivery-safety requirements, not only test-harness accommodations: an explicit custom endpoint is needed for local development and proxies, while invalid source configuration must never silently select a billed network path.
@datadog/openfeature-node-server2.0.1 also contains the latest evaluator correction and needs to be consumed before the Node.js tracer release.Changes
agentless,remote_config, and reservedoffline.offlineor an arbitrary invalid source, before selecting any delivery path.DD_API_KEY, omit the header, and let the endpoint report an authentication failure.@datadog/openfeature-node-serverfrom 2.0.0 to 2.0.1.Decisions
Split scratchpad
This draft preserves the combined investigation and proof while the implementation is split into three separately scoped draft PRs. The configuration-grandfathering PR is stacked on the Docker/custom-endpoint PR; the provider bump is outside that stack and on hold. Do not use this combined branch as the merge path.
Combined state captured here
6ee9987831336ca15627be1a1e60cc678a5cc9eb.2003c40d2989f7cd9ed19cfef0f2d3df76ccaf48.a5dc9b8433ee3fd2892ea2968b90acb26274313c.@datadog/openfeature-node-server@2.0.1.Original commit partition
8a11b63794c6— custom agentless endpoint and Docker/proxy transport support.d58eb1dd35ff— explicit invalid/reserved source handling and configuration grandfathering.6ee998783133— provider dependency update from 2.0.0 to 2.0.1.The first two commits overlap in configuration parsing because they were developed serially. The split branches must reconstruct their final scopes from latest
master, not mechanically preserve that accidental stack.Split PRs
leo.romanovsky/ffl-2697-openfeature-node-server-2.0.1masterpackage.json,yarn.lock, and generated@datadog/js-corelicense attributionleo.romanovsky/ffl-2697-custom-agentless-endpointsmasterleo.romanovsky/ffl-2697-configuration-source-grandfatheringofflinefail-closed behavior, registry and integration testsThe configuration change remains separately scoped from endpoint transport behavior, but #9482 is intentionally stacked on #9481 so CI validates the fail-closed contract with the custom
host.docker.internalDocker delivery surface.CI failure captured before splitting
Two root checks failed on the combined head;
all-greenwas only their aggregate:Project / lint:Missing 3rd-party license for @datadog/js-core.Update 3rd-party licenses / check-licenses: generated exactly one missing row:That row belongs only in the provider-bump PR. With it applied locally, the full
npm run lintcommand passed, including the license checker, ESLint, CODEOWNERS audit, and exercised-test verification.Pending review feedback captured before splitting
DD_API_KEYfor the default Datadog UFC API while allowing a custom API to start without one. The focused unit tests passed after applying this condition locally.Experimental:from all four new Feature Flagging configuration descriptions.These threads remain open on this scratch PR. Their code changes belong in the endpoint and configuration split PRs respectively.
Docker proof after both review changes
The combined local tree was mounted into the already-built PARAMETRIC Node.js image and rerun sequentially:
Result:
This rerun included default custom-endpoint delivery, invalid source, reserved
offline, missing-auth cold and warm paths, recovery, ETag handling, timeout behavior, and poller concurrency. The detailed image/runtime/hash proof remains in the collapsible Motivation block above.Exact earlier-pass/later-failure provenance
51756483a265, dd-trace-js94a16dc3017b, 53 passed plus 18 existing XPASS; configuration sources were 29/29.30338367a818.dcdc37f52275, which replaced the explicithost.docker.internalallowance with a loopback-only HTTPS guard.http://host.docker.internal:<port>; that hostname is not container loopback.Validation allocation for the split
Split PRs now live
c60c2700e1abd3b2e603c86663eadb4314230994. This draft remains blocked: 2.0.1 pulls@datadog/js-corefromDataDog/browser-sdk, so it must not merge in its current form.51cae1bdd2378ecf0f3c77147e2934e33ca2ceb4. This branch is independent onmaster.3395eccc707ff0b06ea504ae668a80017e6787b4. This PR is stacked on fix(openfeature): allow custom agentless endpoints #9481 so CI evaluates the configuration contract with the Docker/custom-endpoint parent.459352867b471ae9c332fd3ee697321fa2dcdbd5.The provider-bump draft will be updated with a new commit after a clean upstream patch release exists. The generated
@datadog/js-corelicense row in #9480 is evidence of the bad 2.0.1 graph, not an acceptable long-term Node.js dependency.