Conversation
`packages/client/src/lifecycle.ts` ran `import 'dotenv/config'` at module
load, so every `@launchdarkly/ai-*` package (all of them depend on
`@launchdarkly/ai-server`) silently loaded whatever `.env` sat in the
consumer's current working directory into `process.env` before the app's
own code ran.
A library must not do that:
- It is cwd-dependent: which file gets loaded depends on where the process
was started, not on anything the consuming app declared.
- It is silent: nothing is logged and no option controls it.
- It fills in unset variables: dotenv does not override existing values, so
the vars it injects are exactly the ones the app had deliberately left
unset, including credentials such as `LD_API_KEY`.
A downstream consumer hit this in practice: a stale token from an unrelated
`.env` was injected on import and LaunchDarkly returned 401.
Changes:
- Remove the side-effect import from `lifecycle.ts`. The module already reads
`process.env` directly and needs nothing else from dotenv.
- Drop `dotenv` from the client package's `dependencies`. It stays as a root
devDependency because `main.ts` and `examples/` are application
entrypoints and may keep opting in.
- Replace the test's `vi.mock('dotenv/config')` stub with a guard that fails
if `lifecycle.ts` (or anything it imports) ever pulls dotenv back in.
- Note in both READMEs that the SDK reads `process.env` only, and that apps
wanting `.env` loading add `import 'dotenv/config'` to their own
entrypoint before importing the SDK.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What the import did
packages/client/src/lifecycle.tsranimport 'dotenv/config'at module load. Because every@launchdarkly/ai-*package depends on@launchdarkly/ai-server, importing any of them loaded whatever.envsat in the consumer's current working directory intoprocess.envbefore the consuming app's own code ran.Why that is a bug for consumers
LD_API_KEY.This bit a downstream consumer (Actuator): a stale token from an unrelated
.envin its working directory was injected on import and LaunchDarkly returned 401. The app had not asked for.envloading and had no way to see it happen.Loading
.envis an application decision. It belongs in entrypoints (main.ts,examples/), where the author opts in, not in library code.What changed
lifecycle.ts. The module readsprocess.envdirectly and needed nothing else from dotenv.dotenvfrom@launchdarkly/ai-server'sdependencies. It stays as a root devDependency formain.tsandexamples/.yarn.lockis unchanged.vi.mock('dotenv/config')stub with a guard that fails iflifecycle.ts(or anything it imports) ever pulls dotenv back in. Verified it fails with the import present and passes without it.process.envonly and does not load.env.How consumers opt in
Add
import 'dotenv/config';to your own entrypoint before importing the SDK. The README examples already do this.Verification
yarn install --frozen-lockfile,yarn build,yarn typecheck,yarn test(824 tests across 8 packages, all passing),yarn code:check,yarn lint:pkg.🤖 Generated with Claude Code