Skip to content

Keep reading every old environment variable name, deprecated - #88

Merged
jwrosewell merged 7 commits into
rcfrom
fix/old-endpoint-name
Nov 12, 2026
Merged

jwrosewell merged 7 commits into
rcfrom
fix/old-endpoint-name

Conversation

@jwrosewell

@jwrosewell jwrosewell commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor

The problem

The last published release, 4.5.102, was built from main 384bff2d (the tags fiftyone.pipeline.cloudrequestengine/4.5.102 and fiftyone.pipeline.did/4.5.102 both point at it). Its packages, tests and examples read environment variables under names that rc a32301da no longer reads. #77 renamed the cloud endpoint variable and #70 gave every other variable one _51DEGREES_ name with nothing behind it. Neither has been published. A deployment, a test set-up or a person running an example who sets one of the old names would, after this patch release, find it ignored with no error and no message. For the endpoint that means calls go to https://cloud.51degrees.com/api/v4/ and not to the private host that was set.

The rules

James Rosewell said, at about 11:40 UTC on 12 November 2026

A patch release never removes or renames a public name. The old name stays for at least one release, deprecated and pointing at the new one.

Asked at about 12:05 UTC whether that covers an environment variable name a package reads as well as names in code, he answered

Yes, env names too

Asked at about 16:55 UTC whether the rule covers environment variable names that tests and examples read, he answered

How could they not be if they're needed for tests?

And examples? Some people will want to run the tests themselves. That's a good thing.

They were always public!!

So every environment variable name that a package, a test, an example or a CI script in this repository reads is a public name. This draft began with the cloud endpoint alone and now covers every such name, in one draft.

The specification does not name any of these variables. A code search of the default branch of specifications at 6570727d finds neither FOD_CLOUD_API_URL nor _51DEGREES_CLOUD_ENDPOINT, so the rules above are what this draft follows.

What was checked

Every read of an environment variable (process.env.NAME, process.env[...], $env:NAME and ${env:NAME}) in every .js, .ps1 and .yml file at main 384bff2 and at rc a32301d, and the constants that hold a variable name. The names main read that rc does not are these.

Old name Name that replaced it Where main read the old name
FOD_CLOUD_API_URL _51DEGREES_CLOUD_ENDPOINT cloudRequestEngine.js line 93, didClient.js line 981, the creator context example server.js line 223
RESOURCE_KEY _51DEGREES_RESOURCE_KEY Behind the new name in gettingStarted.js line 64, exampleUtils.js line 38, integration.test.js line 42, didClient.integration.test.js line 37, server.js line 226, the device detection test key helper through legacyEnvVars, and the IP Intelligence example and tests below. As the only name in the four geolocation examples (for example gettingStarted.js line 115) and geoLocationCloud.test.js line 26
LICENSE_KEY _51DEGREES_LICENSE_KEY As the only name in the six examples that keep a data file up to date (for example updateOnStartUp.js line 64). Behind the new name in server.js line 228 and didClient.integration.test.js line 39
51DEGREES_RESOURCE_KEY _51DEGREES_RESOURCE_KEY gettingStarted.js line 59, exampleUtils.js line 30, the fiftyone.ipintelligence test at line 35, the fiftyone.ipintelligence.cloud test at line 37
51DEGREES_DD_PATH _51DEGREES_DD_PATH exampleUtils.js line 52, exampleUtils.js line 56
51DEGREES_IPI_PATH _51DEGREES_IPI_PATH exampleUtils.js line 51
TEST_SUPER_RESOURCE_KEY, TEST_PLATFORM_RESOURCE_KEY, TEST_HARDWARE_RESOURCE_KEY, TEST_BROWSER_RESOURCE_KEY, TEST_NO_SETHEADER_RESOURCE_KEY _51DEGREES_RESOURCE_KEY_SUPER and the matching _PLATFORM, _HARDWARE, _BROWSER and _NO_SETHEADER names The device detection test key helper, keyUtils.js line 38 through legacyEnvVars. The IP Intelligence example tests read TEST_SUPER_RESOURCE_KEY through superResourceKeyEnvVar

TEST_IPI_RESOURCE_KEY and TEST_LICENSE_KEY were held in constants on main and read by nothing, so their constants come back and there is no read to restore. The CI scripts on main set some old names and read none of them, so no CI script changes, and CI goes on setting only the _51DEGREES_ names.

No package held FOD_CLOUD_API_URL in a public constant, member or setting. The constants that held one of the other names are listed under "Constants" below.

What changed

Every old name above is read again, only when the name that replaced it is unset or empty, and the first read that finds a value there says once that the old name is deprecated and which name replaces it. When both are set the new name wins. Everything that tells a reader which variable to set still names only the _51DEGREES_ name.

The cloud endpoint

Cloud Request Engine. The constructor reads _51DEGREES_CLOUD_ENDPOINT first, then FOD_CLOUD_API_URL (cloudRequestEngine.js lines 163 to 178). The baseURL option still wins over both. An engine whose endpoint came from the old name logs one warn message to its Pipeline (lines 54 to 70, called from process at line 283). The message is in errorMessages.js lines 38 to 44 and reads

The FOD_CLOUD_API_URL environment variable is deprecated and _51DEGREES_CLOUD_ENDPOINT replaces it. The cloud endpoint was read from FOD_CLOUD_API_URL because _51DEGREES_CLOUD_ENDPOINT is not set. Set _51DEGREES_CLOUD_ENDPOINT to the same value.

51Did client. environmentEndpoint reads the two names in the same order (didClient.js lines 1012 to 1040). The endpoint option still wins over both, and the environment is not read when it is given. The first client that takes its endpoint from the old name raises one Node DeprecationWarning for the process, with the same wording (lines 37 to 44).

Creator context example. The server no longer reads the endpoint variable itself. It builds its client with no endpoint and gives the page the base the client settled on (server.js lines 250 to 267).

Documents. The engine's readme (lines 70 to 73) and the 51Did readme (lines 462 to 469 and line 848) say the old endpoint name is deprecated and still read. The comments on the endpoint option and on DEFAULT_ENDPOINT say the same, in didClient.js and in the matching lines of types/didClient.d.ts, and types/errorMessages.d.ts gains the new message name. Both type files were edited by hand to match what the type generator copies from the comments.

The keys and data file paths of tests and examples

The message each of these prints, once for each old name in a process, is "The <old name> environment variable is deprecated and <new name> replaces it. Set <new name> instead."

Where What reads the old name again
Pipeline tests findKey in the two liveCloudKeys.js helpers reads RESOURCE_KEY last in RESOURCE_KEY_NAMES (liveCloudKeys.js lines 38 to 83, liveCloudKeys.js lines 38 to 92). The 51Did helper gains LICENCE_KEY_NAMES, ending in LICENSE_KEY (lines 72 to 76), which didClient.integration.test.js line 37 now reads the licence key through
Device detection tests getResourceKey reads the name legacyEnvVars gives for each key (keyUtils.js lines 66 to 90). The two cloud tests that read the key themselves read RESOURCE_KEY behind it (deviceDetectionCloud.test.js lines 34 to 42, deviceDetectionCloud.test.js lines 54 to 62)
IP Intelligence tests resourceKeyNames puts the deprecated names of the names it is given last, being 51DEGREES_RESOURCE_KEY, RESOURCE_KEY and TEST_SUPER_RESOURCE_KEY, and getResourceKey says when one is used (keyUtils.js lines 33 to 124)
Geolocation test geoLocationCloud.test.js lines 32 to 43
Cloud example helpers getResourceKeyFromEnv in device detection (RESOURCE_KEY) and IP Intelligence (51DEGREES_RESOURCE_KEY, then RESOURCE_KEY)
On-premise example helpers getDataFilePathFromEnv in device detection (51DEGREES_DD_PATH), and getDataFilePathFromEnv and findDeviceDataFile in IP Intelligence (51DEGREES_IPI_PATH and 51DEGREES_DD_PATH). updatedatafile.js now reads the path through the helper
Examples that read a key themselves The two gettingStarted.js examples (device detection, IP Intelligence), the four geolocation examples (for example gettingStarted.js lines 115 to 123), the six automatic update examples (for example updateOnStartUp.js lines 62 to 72) and the creator context example (server.js lines 214 to 230)

The two tests that run the on-premise examples with no settings also remove the old names from the environment they give the examples.

Constants

Removed constants are back under their old names with their old values, each marked @deprecated and pointing at the name in use.

  1. legacyEnvVars and envVars.licenseKeyEnvVar in the device detection test constants (testConstants.js lines 36 to 53), which fiftyone.devicedetection.shared exports, with their types.
  2. envVars.ipiResourceKeyEnvVar and envVars.licenseKeyEnvVar in the IP Intelligence test constants (testConstants.js lines 25 to 44), which fiftyone.ipintelligence.shared exports, with their types.
  3. LEGACY_RESOURCE_KEY_ENV_VAR in both cloud example helpers and LEGACY_DATA_FILE_PATH_ENV_VAR in the device detection on-premise example helper.

Five constants kept their names and had their values changed to the new name. Each holds its old value again, marked @deprecated, and a new constant beside it holds the name in use.

Constant Value on main, restored New constant for the name in use
envVars.superResourceKeyEnvVar, IP Intelligence test constants TEST_SUPER_RESOURCE_KEY envVars.superResourceKeyVariable
RESOURCE_KEY_ENV_VAR, IP Intelligence cloud example helper 51DEGREES_RESOURCE_KEY RESOURCE_KEY_VARIABLE
DATA_FILE_PATH_ENV_VAR, device detection on-premise example helper 51DEGREES_DD_PATH DATA_FILE_PATH_VARIABLE
IPI_DATA_FILE_ENV_VAR, IP Intelligence on-premise example helper 51DEGREES_IPI_PATH IPI_DATA_FILE_VARIABLE
DD_DATA_FILE_ENV_VAR, IP Intelligence on-premise example helper 51DEGREES_DD_PATH DD_DATA_FILE_VARIABLE

The examples and tests that used those five to read a variable, or to tell a reader which variable to set, use the new constants, so what is read first and what is printed do not change.

The variable name check

ci/tests/environmentVariableNames.test.js failed on a digit-initial name, a read of a bare RESOURCE_KEY or LICENSE_KEY, or the old endpoint name, anywhere in the repository. It now allows each only in the files that read it as a deprecated fallback or document it (five files, 16 files and six files), still fails on it anywhere else, and fails when a listed file no longer carries it (lines 195 to 229), so no list can outlast the deprecated names.

Decisions made in this draft, for review

  1. How the 51Did client reports the endpoint deprecation. The deprecation has to be logged once. The 51Did package has no logger of its own (no logger option, and no console call in its package code), so the client uses process.emitWarning with the type DeprecationWarning, which is Node's own route for a deprecation. Node writes it to standard error once, passes it to any process.on('warning') listener and leaves it out under --no-deprecation. A browser has no environment variables, so nothing is read or reported there.
  2. When the engine logs. The engine's logger is its Pipeline's, and an engine has no Pipeline when it is built. A message logged while the Pipeline is being built would reach no one, because a listener can only be attached once the Pipeline exists. So the message is logged on the first process, once for each engine that read the old name. A Pipeline with no warn listener drops the message, as it drops every other warning the engine logs (pipeline.js lines 222 to 229).
  3. Tests and examples print with console.warn. A test helper or an example has no logger, so each prints the message to standard error, once for each old name in a process.
  4. New name first, everywhere. On main the geolocation examples and test and the automatic update examples read only the old name, and the device detection on-premise helper read 51DEGREES_DD_PATH before _51DEGREES_DD_PATH. Here the _51DEGREES_ name is always read first, as the rule says the new name wins.
  5. Constants in example helper files are treated as public. The five constants in the table above include four that only an exampleUtils.js file exports. The rule speaks of a public constant, and James's words make what tests and examples read public, so the four are restored as the exported test constants are. If a constant that only an example's helper file exports is not public, the four and their new _VARIABLE constants can go back to how rc has them with no change in what is read.

Tests

Each change was tested first, with the tests pushed alone and built before the fix.

Step Tests alone Fix
The cloud endpoint 323b0acd 935f1b56, then 66937e33, which corrected three test comments after a review
Every other old name bb399541 74e8fa38
The five constants e360178d 0dced2bd, the head
Test file What the tests say
cloudRequestEngine.test.js lines 79 to 191 Only the old endpoint name set gives that endpoint, with the new name unset and with it empty. Both set gives the new name's endpoint. Neither set, or the old name empty, gives the default. Two processes log exactly one warning naming both names. Nothing is logged when the new name or baseURL is used, or for the default
didClient.test.js lines 296 to 363 The same endpoint cases for the client. Two clients raise exactly one DeprecationWarning naming both names. None is raised when the old name is not used
creatorContextServer.test.js lines 201 to 300 The example is started as its own process three times, and the page it serves carries the old name's endpoint, the new name's endpoint when both are set, and the public cloud when neither is
ci/tests/deprecatedVariableNames.test.js For each of 18 reads through a helper (lines 85 to 127), only the old name set gives its value and prints the deprecation exactly once over two reads, the new name empty still gives the old value, both set gives the new value and prints nothing, and neither set gives nothing. Each of 15 example and old name pairs (lines 162 to 174) is started as its own process with only the old name set and has to print the deprecation naming both names. Six tests check the constants (lines 272 to 328)
environmentVariableNames.test.js lines 195 to 229 Each old name appears only in its listed files, and every listed file carries it

There is no test that an old endpoint constant still holds "FOD_CLOUD_API_URL", because Node never had such a constant.

Red runs. Each is the full build on a tests-only commit, and in each the Ubuntu_ARM_Node_22 job failed and the other five build jobs were cancelled when it failed.

  1. Run 43245060203 on 323b0ac. 8 tests failed and 1241 passed. The eight are the endpoint tests and no others, for example DidClient construction › endpoint reads the old variable name when the new one is not set (expected https://old.example/api/v4/, received https://cloud.51degrees.com/api/v4/) and custom end point - old variable name logged once (expected one warning, received none).
  2. Run 43269342664 on bb39954. 58 tests failed and 1281 passed. All 58 are new, 56 in deprecatedVariableNames.test.js and the two list tests in environmentVariableNames.test.js, for example cloud request engine tests (0) › reads RESOURCE_KEY when _51DEGREES_RESOURCE_KEY is not set, and says once that it is deprecated (expected old-value, received an empty string).
  3. Run 43276354274 on e360178. 3 tests failed and 1339 passed. The three are the new constant tests and no others, for example constants that held an old name › hold their old values in the cloud example helpers (expected 51DEGREES_RESOURCE_KEY, received _51DEGREES_RESOURCE_KEY).

Green run. Run 43279049770, the full build on the head 0dced2b, finished with success. All seven Setting 'PullRequestSha' lines, one in Configure and one in each of the six build jobs, read 0dced2b. Configure printed "Left out 2 macOS entries". Each of the six build jobs (Ubuntu, Ubuntu ARM and Windows, on Node 22 and Node 24) reports 1342 unit tests passed and 2 skipped of 1344, and 132 integration tests passed and 4 skipped of 136. Lint reports 0 errors. The Complete job printed "Dry run - not merging". Two earlier heads also had green full builds, 66937e3 in run 43260670425 and 74e8fa3 in run 43273805487.

macOS was left out of this draft's full build under the 9 November decision. The rc head is built with macOS before it merges into main.

What remains

  1. The release draft #83 says under its thirteenth point that the old endpoint name is no longer read, and lists the other renames as breaking. Once this draft merges, those points need to say each old name is deprecated and still read for this release. This draft does not change Release candidate #83.
  2. A later release removes the reads of the old names. The variable name check will then fail until each file is taken off its list, which is the reminder to remove the readme text, the messages and the deprecated constants with them.
  3. Decision 5 above is open for James as a rule, which is whether a constant that only an example's helper file exports counts as a public constant.

The cloud request engine, the 51Did client and the creator context
example must read _51DEGREES_CLOUD_ENDPOINT first and, when that is unset
or empty, FOD_CLOUD_API_URL, reporting once that the old name is
deprecated. These tests say so and fail until the old name is read again.

The environment variable name check now allows the old name in the files
that will read or document it, and fails while a listed file does not
name it.
The rename of the cloud endpoint variable to _51DEGREES_CLOUD_ENDPOINT
stopped reading FOD_CLOUD_API_URL, which the last release read. A patch
release must not drop a name a caller may have set, so the old name is
read again for this release, deprecated.

The cloud request engine and the 51Did client read
_51DEGREES_CLOUD_ENDPOINT first. When that is unset or empty they read
FOD_CLOUD_API_URL and say once that it is deprecated. The engine logs a
warn message to its Pipeline on the first process, because it has no
Pipeline when it is built. The 51Did package has no logger, so the client
raises one Node DeprecationWarning for the process.

The creator context example no longer reads the variable itself. It
builds its client with no endpoint and gives the page the base the client
settled on, so it follows the same rule.

Neither package held the variable name in a public constant, so there is
no constant to restore.
The variable name check said every variable has one name with nothing
behind it, which is no longer true of the cloud endpoint, so the comment
now speaks of the resource key and the licence key alone. The title of
its old name test said the name appears only where it is still read, when
four of the six listed files word or document it without reading it.

The header of the creator context server test described only the /redeem
route. It now also says the endpoint tests start the example as its own
process and ask for its page over the loopback address.

No code or test behaviour changes.
Tests, test helpers and examples read their keys and data file paths
from names such as RESOURCE_KEY, LICENSE_KEY, the TEST_ key names and
names starting with the digit, until those names were aligned on the
_51DEGREES_ prefix. Every such name is public, so each must still be
read, deprecated, when the name that replaced it is unset or empty.

The new tests set only the old name and check that the value is used and
that the deprecation is printed once, naming the new name. They cover the
key helpers of the pipeline, device detection and IP Intelligence tests,
the example helpers, the constants that held an old name and each example
that reads a variable itself. They fail until the old names are read
again.

The environment variable name check now allows a digit-initial name and
a read of a bare key name in the files that will read them as fallbacks,
and fails while a listed file does not carry one.
…d it

Every environment variable name that a package, a test, an example or a
CI script reads is a public name, and a patch release never removes or
renames one. The alignment on the _51DEGREES_ prefix dropped these names,
which the last release read:

- RESOURCE_KEY, behind _51DEGREES_RESOURCE_KEY
- LICENSE_KEY, behind _51DEGREES_LICENSE_KEY
- 51DEGREES_RESOURCE_KEY, 51DEGREES_DD_PATH and 51DEGREES_IPI_PATH,
  behind the same names with a leading underscore
- TEST_SUPER_RESOURCE_KEY, TEST_PLATFORM_RESOURCE_KEY,
  TEST_HARDWARE_RESOURCE_KEY, TEST_BROWSER_RESOURCE_KEY and
  TEST_NO_SETHEADER_RESOURCE_KEY, behind the _51DEGREES_RESOURCE_KEY_
  names

Each is read again, only when the name that replaced it is unset or
empty, and the first read that finds a value there prints once that the
old name is deprecated and which name replaces it. The test key helpers
and the example helpers do this in one place each, and the examples and
tests that read a variable themselves do it where they read.

The constants that held an old name are back under their old names with
their old values, marked deprecated: legacyEnvVars and licenseKeyEnvVar
in the device detection test constants, ipiResourceKeyEnvVar and
licenseKeyEnvVar in the IP Intelligence test constants, and
LEGACY_RESOURCE_KEY_ENV_VAR and LEGACY_DATA_FILE_PATH_ENV_VAR in the
example helpers.

The messages that tell a reader which variable to set still name only
the _51DEGREES_ names.
Five exported constants kept their names when the variable they name was
renamed, and now hold the new name. Code that passes one of them to the
environment would no longer read the variable it read before, so each
must hold its old value again, with a new constant for the name in use.

These tests say so for superResourceKeyEnvVar in the IP Intelligence test
constants, RESOURCE_KEY_ENV_VAR in the IP Intelligence cloud example
helper, DATA_FILE_PATH_ENV_VAR in the device detection on-premise example
helper, and IPI_DATA_FILE_ENV_VAR and DD_DATA_FILE_ENV_VAR in the IP
Intelligence on-premise example helper. They fail until the values are
restored.
Five exported constants kept their names when the variable they name was
renamed, and held the new name. Code that passes one of them to the
environment would no longer read the variable it read before, so each
holds its old value again, marked deprecated, and a new constant beside
it holds the name in use:

- superResourceKeyEnvVar in the IP Intelligence test constants is
  TEST_SUPER_RESOURCE_KEY again, with superResourceKeyVariable
- RESOURCE_KEY_ENV_VAR in the IP Intelligence cloud example helper is
  51DEGREES_RESOURCE_KEY again, with RESOURCE_KEY_VARIABLE
- DATA_FILE_PATH_ENV_VAR in the device detection on-premise example
  helper is 51DEGREES_DD_PATH again, with DATA_FILE_PATH_VARIABLE
- IPI_DATA_FILE_ENV_VAR and DD_DATA_FILE_ENV_VAR in the IP Intelligence
  on-premise example helper are 51DEGREES_IPI_PATH and 51DEGREES_DD_PATH
  again, with IPI_DATA_FILE_VARIABLE and DD_DATA_FILE_VARIABLE

The examples and tests that used those constants to read a variable, or
to tell a reader which variable to set, use the new constants, so what
is read first and what is printed do not change.
@jwrosewell jwrosewell changed the title Keep reading the old cloud endpoint variable name, deprecated Keep reading every old environment variable name, deprecated Nov 12, 2026
@jwrosewell
jwrosewell marked this pull request as ready for review November 12, 2026 19:24
@jwrosewell
jwrosewell merged commit 871e7a3 into rc Nov 12, 2026
2 checks passed
@jwrosewell
jwrosewell deleted the fix/old-endpoint-name branch November 12, 2026 19:24
@jwrosewell jwrosewell mentioned this pull request Nov 12, 2026
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.

1 participant