# Configuration 101: what did the program actually load?

A fictional service prepares a maintenance-response draft. Before it can create a model client, it needs settings: an attempt limit and a credential. The code works in one launch but stops in another. Start with the settings reaching the program, before changing the model or framework.

This original 40-minute lab runs real Node.js processes and reads a generated local dotenv file. It uses no model, network, provider credential, package installation or cloud account. Its generated credential has no authority anywhere. Do not put real credentials into this exercise.

## 1. Name the pieces before configuring a client

**Configuration** means settings that control how a program runs. An attempt limit is ordinary configuration. A credential is sensitive configuration. Both might reach an application through environment variables, but they need different handling in logs, source control and access policy.

A **process** is one running instance of a program. An **environment variable** is a named text value available to that process. A **dotenv file** is a text file of name=value lines. It is an input to a loader, not the process environment itself. In this lab, Node's `--env-file` option performs the loading. A framework can have its own automatic loading and precedence rules; do not generalize this command's behavior to every framework.

Think of the same function run with different arguments: the implementation stays the same while inputs change its behavior. The analogy has a limit. Configuration often arrives when the application starts and remains in memory; it is not automatically refreshed with every request.

An SDK is another component. It uses the configuration your application supplies, then prepares a service request. Loading a nonempty credential does not prove that it is valid, scoped correctly or accepted by that service.

## 2. Trace one setting and decide what may be shown

The fictional setting `DEMO_MAX_ATTEMPTS` is a limit from 1 to 5. The program reads it as text and explicitly converts a valid value to a number. `DEMO_CREDENTIAL` is generated inside the exercise. The output reports only `credentialConfigured: true` or `false`, never its value.

Follow this path: **file and launch settings → process environment → application validation → allowlisted diagnostic**. Precedence is the rule for deciding which source wins when two define the same name. For Node's `--env-file`, an inherited value takes priority over the file's value.

Do not confuse parsing with validation. A dotenv parser can load the word `many`. The application's startup rule still rejects it as an attempt limit. The rule names the expected range without echoing an arbitrary rejected input. A missing required credential also stops the example before client creation; there is no silent fallback to another account.

The script never creates a client or tries authentication. `configuration-ready` means only that this example's local startup checks passed. It is not a service-health result.

## 3. Predict and run six local cases

Download `fde-configuration-lab.mjs` into a new folder. Use Node.js 24 and an ordinary local terminal. The script creates one temporary folder, writes its own `.env.demo`, launches only its own worker and removes that folder afterward. Existing files, shell settings and deployment settings are unchanged. Children receive an explicit lab environment, not the parent terminal's environment. The temporary file uses owner-only permissions where the operating system supports them; this is still a teaching fixture, not a production secret store.

```sh
node --version
node fde-configuration-lab.mjs
```

Before running, predict each result. The JSON report is the actual output of local child processes, not expected-output text printed as though it were observed. Cases intentionally stop on missing or invalid settings; exit code 2 is this example's startup refusal. The overall command exits successfully when it completes the experiment, including those refusals.

| Case | What changes | Predict before running |
| --- | --- | --- |
| not-loaded | The file exists, but plain Node starts without `--env-file` | Does the process have the required variables? |
| file-loaded | The launcher includes `--env-file` | What type does the limit have before conversion? |
| inherited-wins | The file says 2; the launcher supplies 4 | Which limit does the process actually use? |
| invalid-string | The file contains a word instead of a bounded integer | Does loading the file make the app ready? |
| file-edit | A process starts with 2; the driver changes the file to 5 while it stays alive | What does the existing process see? What does a new process see? |
| child-change | A child starts with 3, then changes its own variable to 5 | What does the next sibling receive from the unchanged launcher? |

Read `inspectConfiguration` first. It is the application rule. Then locate the `env` option passed to each child process and the `--env-file` argument. The script uses the current Node executable directly; it does not ask a shell to expand a command. The file-edit case uses a local inter-process message to coordinate when to reread the existing process environment. That message is a timing signal, not a file reload.

## 4. Compare the observations with your predictions

**not-loaded:** the process reports missing credential and invalid/missing limit, then exits 2. The nearby file did not load itself. **file-loaded:** input type is string, the validated limit is number 2, credential presence is true and exit is 0. Those are the startup conditions this app checks.

**inherited-wins:** the effective limit is 4, despite the file's 2. Diagnose the launch environment and its precedence before editing the same file repeatedly. **invalid-string:** the parser accepts text, while the application stops with `maxAttempts: null`. The diagnostic gives a fixed rule rather than copying an untrusted or potentially sensitive value into logs.

**file-edit:** the first process reports 2 before and after the driver edits the file. A newly launched process reports 5. This program does not reread the file after startup. Some applications implement reloads or watch configuration stores; those mechanisms need their own consistency, validation and failure behavior.

**child-change:** one child's own environment changes from 3 to 5. The next sibling reports 3. Neither the parent's launch dictionary nor the file was modified by that child change. A process-local assignment does not reconfigure every process or update a cloud deployment.

These observations establish behavior of this local program on the recorded Node version. They do not test a cloud secret manager, credential rotation, a framework's client bundling, provider authentication or multiple production replicas. Keep those receiving checks separate from the evidence this lab supplies.

## 5. Change one cause at a time

Make two independent copies of the downloaded file. Never edit the generated credential or add a real one.

In the first copy, change `INHERIT_OVERRIDE = true` to `INHERIT_OVERRIDE = false`. Predict `inherited-wins`, run the copy and record its effective limit. It should now use 2 from the file because the competing launch value was removed. This explains the cause of the difference; merely changing the diagnostic would not repair it.

In the second copy, start from the original and change `INVALID_ATTEMPTS = "many"` to `INVALID_ATTEMPTS = "3"`. Run again. The `invalid-string` case retains its case label but now passes the startup rule with number 3. It is the changed input and actual decision that matter, not the label. Explain why this still says nothing about credential validity.

Keep the original observations beside each changed-copy result. Record the exact constant you changed and one outcome you expected to remain unchanged. Do not combine the changes until you can explain each independently.

## 6. Hand over configuration without handing over secrets

Create a small configuration card for an application you understand. Name each required setting, its purpose, its owner, where it comes from, which process consumes it and whether a change requires restart or explicit reload. Record types and safe ranges, loader precedence and a missing-setting response. For a credential, record the approved reference or delivery mechanism and a presence check; omit the value.

In a real project, keep sensitive files out of source control and use the organization's approved secret storage and workload identity mechanisms. A `.env` file is plain text, and placing a value in an environment variable does not make it encrypted or inaccessible. Avoid environment dumps, secrets in command arguments, browser-visible configuration, screenshots and diagnostic exports. An example file can document names with empty placeholders; a public example must not contain a usable credential.

For a deployment, distinguish settings supplied during a build from those supplied to the running service. Some toolchains substitute build-time values into generated browser code. A server credential belongs in a restricted server-side path, not a public browser bundle. Verify your actual framework's behavior and the intended running version; do not assume that changing one console setting updates every existing process.

Explain the fictional incident to a colleague: “The file says two, but this process received four from its launcher. I can show the effective nonsecret limit and whether the required credential is present. I do not need the credential value to diagnose precedence.” Then continue to the SDK lesson and distinguish configuration readiness from the first actual request.

Primary references checked 22 October 2026: [Node.js 24 environment variables](https://nodejs.org/docs/latest-v24.x/api/environment_variables.html), [process environment](https://nodejs.org/docs/latest-v24.x/api/process.html#processenv) and [Node's env-file option](https://nodejs.org/docs/latest-v24.x/api/cli.html#--env-fileconfig). The instruction and experiment here are original LockedIn Labs material.
