WEB / WEB-16.02
Configuration and secrets
Configuration arrives as input, which the application validates and consumes. Environment changes, running-process snapshots, and secret rotation are different events.
1. Core · Mechanism
Read every scenario without motion
Valid config
- Synthetic input
The example supplies mode=public and limit="2" as text inputs. Validation and process startup have not yet occurred.
- Startup input
- cfg-a; public; text "2"
- Config validator
- Not validated
- Running process
- Not started
- Dependency metadata
- Unused
- Local required check
The validator locally checks required mode/limit fields and allowed enum public.
- Startup input
- cfg-a; public; text "2"
- Config validator
- Required/enum pass
- Running process
- Not started
- Dependency metadata
- Unused
- Local type check
The decimal string "2" converts to integer 2 and satisfies the educational range 1..10.
- Startup input
- cfg-a; public; text "2"
- Config validator
- Typed limit=2; range pass
- Running process
- Not started
- Dependency metadata
- Unused
- Accept snapshot
Validated cfg-a becomes one immutable snapshot; source text was not automatically typed.
- Startup input
- Source cfg-a
- Config validator
- Snapshot cfg-a limit=2
- Running process
- Not started
- Dependency metadata
- Unused
- Process consumes
The local process consumes cfg-a/limit2 at startup and enters a separate local listening state.
- Startup input
- Source cfg-a
- Config validator
- Snapshot cfg-a limit=2
- Running process
- Listening; effective cfg-a limit=2
- Dependency metadata
- Unused
- Effective outcome
The service records effective revision and harmless typed value without credential material.
- Startup input
- Source cfg-a
- Config validator
- Validated snapshot
- Running process
- Effective cfg-a limit=2
- Dependency metadata
- No secret value
Invalid type
- Synthetic bad text
The limit input is the text "two" rather than a decimal integer. The process has not accepted this input or started listening.
- Startup input
- cfg-invalid; public; two
- Config validator
- Not validated
- Running process
- Not started
- Dependency metadata
- Unused
- Local enum check
Mode public is valid while the limit type check has not completed.
- Startup input
- cfg-invalid; public; two
- Config validator
- Mode pass; limit pending
- Running process
- Not started
- Dependency metadata
- Unused
- Local type reject
The decimal-integer rule rejects two without accepting a truthy string.
- Startup input
- cfg-invalid; public; two
- Config validator
- Rejected invalid-limit
- Running process
- Not started
- Dependency metadata
- Unused
- Startup stops
Failed required validation prevents listening, so no request arrival is modeled.
- Startup input
- Invalid input retained
- Config validator
- No accepted snapshot
- Running process
- Not listening
- Dependency metadata
- Unused
- Failure outcome
The harmless invalid-limit category is recorded without displaying a full environment dump.
- Startup input
- Invalid input retained
- Config validator
- Rejected
- Running process
- Startup rejected
- Dependency metadata
- No secret value
Version transition
- Old snapshot
Initial source/consumer/accepted metadata is sec-ref-a, a noncredential alias.
- Startup input
- Source cfg-a
- Config validator
- Validated cfg-a
- Running process
- Consumer sec-ref-a
- Dependency metadata
- Accept sec-ref-a
- Source moves
The supplied source moves to cfg-b/sec-ref-b while the running consumer retains its old snapshot.
- Startup input
- Source cfg-b sec-ref-b
- Config validator
- Old snapshot cfg-a
- Running process
- Consumer sec-ref-a
- Dependency metadata
- Accept sec-ref-a
- Revoke old version
Supplied downstream acceptance changes to sec-ref-b only, separately from source-label rotation.
- Startup input
- Source cfg-b sec-ref-b
- Config validator
- Old snapshot cfg-a
- Running process
- Consumer sec-ref-a
- Dependency metadata
- Accept sec-ref-b; a revoked
- Old consumer reject
The local metadata predicate finds old consumer a absent from the accepted set.
- Startup input
- Source cfg-b sec-ref-b
- Config validator
- Old snapshot cfg-a
- Running process
- Dependency unavailable
- Dependency metadata
- Old a rejected
- Validate replacement
A new cfg-b snapshot with public/limit3 and sec-ref-b is separately validated.
- Startup input
- Source cfg-b sec-ref-b
- Config validator
- Validated cfg-b limit=3
- Running process
- Old consumer a
- Dependency metadata
- Accept sec-ref-b
- Replace snapshot
The selected policy replaces one validated snapshot rather than automatically refreshing external environment.
- Startup input
- Source cfg-b sec-ref-b
- Config validator
- Validated cfg-b limit=3
- Running process
- Consumer sec-ref-b
- Dependency metadata
- Accept sec-ref-b
- New consumer accept
The local metadata predicate accepts b without measuring vault cryptography or credential authentication.
- Startup input
- Source cfg-b sec-ref-b
- Config validator
- Validated cfg-b limit=3
- Running process
- Dependency available
- Dependency metadata
- New b accepted
ACTORS · STATE · DATA FLOW
Environment carries input, not a type contract
Environment variables are key/value inputs associated with the process startup environment. Node process.env exposes that process environment object; DotEnv parses additional values as text. The strings false, 0, or JSON-looking text do not automatically become booleans, numbers, or objects. Configuration loading must specify its input source and conversion to typed values.
The Atlas public-note service receives synthetic ATLAS_FIXTURE_MODE=public and ATLAS_FIXTURE_LIMIT="2". The application validates mode against an allowed enum and limit as a decimal integer in the selected educational range 1..10. This range is not production capacity advice. Successful validation produces normalized {mode:public,limit:2}; ordinary invalid text such as two is rejected, without relying on truthy strings.
Precedence among defaults, environment, and explicit overrides is an application contract, not a universal runtime priority. This example uses explicit input and records the accepted revision. Missing or invalid required input stops startup; do not animate request arrival before a server listens. Configuration does not replace database authorization or policy enforcement.
A running process has its own consumption lifecycle
Configuration can be read once at startup and converted to a frozen object. Moving a deployment source to cfg-b does not automatically refresh a running process using a cfg-a snapshot. This is not because environment is forever immutable: application code can change process.env. Read timing and reconstruction of cached clients or connections are application decisions.
Local Node process.env changes do not automatically update the parent shell or default Worker environment copies. Explicit shared-environment Worker options behave differently and are excluded here. Passing an explicit synthetic environment to a new child creates a new snapshot, not a remote control channel that updates the existing process.
Hot reload needs explicit revision, validation, and transition atomicity. Combining one new field with another old field creates mixed configuration. This example replaces a single validated immutable snapshot; restart or provider notification is not automatic in every application. Startup success, readiness, and dependency availability remain separate observations.
Secret delivery, use, and revocation differ
A secret is material whose exposure affects access or cryptographic protection; not every configuration field is secret. A public theme or limit differs from a database credential/private key. Environment injection can deliver a secret, but alone provides no vault, access control, encryption at rest, auditing, or rotation. Protect lifecycle separately across source repositories, build images, plaintext logs, and dumps.
Secret management controls versions, authorized consumers, rotation, revocation, and expiry. OWASP recommends least privilege and usage/audit metadata without logging values. Rotation depends on secret type and dependency; do not generalize one periodic policy to application service keys and human passwords. An old version can remain accepted downstream after rotation, so changing a source label is not equivalent to revocation.
The artifact carries only noncredential sec-ref-a/sec-ref-b aliases and accepted-version metadata. When the supplied source moves to b, the running process continues using a. A downstream accepting b and revoking a makes the old consumer dependencyUnavailable. A newly validated snapshot using b passes the selected dependency check. These states are neither real vault responses nor usable tokens; diagnosis needs no displayed secret value.
2. Red · Trust & Impact
Read every scenario without motion
Invalid startup
- The startup-input contract was selected
ATLAS_FIXTURE_MODE=public and ATLAS_FIXTURE_LIMIT=two are fixed supplied inputs. No actual environment or secret file is read.
- Config/version source
- cfg-invalid input
- Consumer validation
- Type validation not performed
- Service/acceptance boundary
- Service not listening
- String and typed limits were separated
The limit must be a decimal integer under educationalMin=1 and educationalMax=10. String two is not a numeric limit under this contract.
- Config/version source
- Raw limit="two"
- Consumer validation
- Decimal-integer gate failed
- Service/acceptance boundary
- Service not listening
- Startup acceptance was withheld
startupOutcome remains rejected. A nonempty string being truthy does not establish that configuration type or enum validation passed.
- Config/version source
- Invalid public input
- Consumer validation
- Startup rejected
- Service/acceptance boundary
- Service not listening
- No default permission was manufactured
This invalid input is not treated as replaced by "2" from validInput. Rejection does not establish an approved effective revision or policy authority.
- Config/version source
- cfg-invalid retained for diagnosis
- Consumer validation
- No normalized limit
- Service/acceptance boundary
- No accepted configuration
- The listening outcome was read separately
listening=false is the negative execution boundary. The fixture explains input rejection; it measures no actual deployment, process crash or production availability.
- Config/version source
- Known: invalid limit
- Consumer validation
- Known: startup rejected
- Service/acceptance boundary
- Known: listening=false
- The configuration trust boundary was preserved
An approved new snapshot is selected only after validation. Environment-delivery format or variable names do not prove trusted typed policy values.
- Config/version source
- No accepted snapshot
- Consumer validation
- Type gate remained closed
- Service/acceptance boundary
- No service activation claim
Old consumer
- The version-transition scope was selected
secretVersions separates source, consumer and accepted aliases. sec-ref-a and sec-ref-b are not actual credentials; the artifact contains no secret value.
- Config/version source
- Version aliases only
- Consumer validation
- Consumer state not read
- Service/acceptance boundary
- No acceptance outcome
- Source rotation was read separately
rotatedSource=sec-ref-b coexists with oldConsumer=sec-ref-a. A source change does not automatically refresh cached process-consumption state.
- Config/version source
- Source=sec-ref-b
- Consumer validation
- Old consumer=sec-ref-a
- Service/acceptance boundary
- No acceptance outcome
- The downstream accepted set was examined
afterRevocationAccepted contains only sec-ref-b. This accepted set is supplied as a separate downstream-revocation outcome, not inferred from source rotation.
- Config/version source
- Source=sec-ref-b
- Consumer validation
- Consumer=sec-ref-a
- Service/acceptance boundary
- Accepted=[sec-ref-b]
- The old consumer was not accepted
oldConsumerAccepted=false is the outcome of the selected transition. A stale version can cause dependency failure; this denial alone does not attribute secret compromise.
- Config/version source
- Source=sec-ref-b
- Consumer validation
- Consumer=sec-ref-a
- Service/acceptance boundary
- Old consumer accepted=false
- The new consumer remained a separate control
newConsumer=sec-ref-b has newConsumerAccepted=true. This positive control does not mean the old process has already reloaded.
- Config/version source
- New source version known
- Consumer validation
- Old/new consumer contexts separate
- Service/acceptance boundary
- New accepted; old rejected
- Rotation was not equated with revocation
The rotationImpliesRevocation=false boundary remains. Source, consumption and acceptance owners are verified separately; dumping every secret is unnecessary for this correlation.
- Config/version source
- Known: source b
- Consumer validation
- Known: consumer a
- Service/acceptance boundary
- Known: explicit downstream rejection
ASSUMPTION · BOUNDARY · CONTROL
Breaking text and snapshot assumptions
Accepting the strings false or two as truthy without converting to expected types can make mode/limit decisions incorrect. The broken assumption is that environment input is already normalized. Impact depends on how the application uses the field: wrong readiness, availability, or policy branches. This lesson rejects ordinary invalid input at startup without constructing an exploit payload or production-parameter recipe.
Assuming an old process adopted new config just because source revision changed creates a different failure. With cached cfg-a, deployed cfg-b metadata does not prove effective state. Record accepted revision and effective typed fields separately without secret values. Changed default/override precedence also needs verification rather than an assumption of unchanged behavior.
Do not confuse delivery with secret protection
Treating injected material as an automatically protected vault loses the access boundary. Evaluate required roles, source-read permission, and consumption context; dumping full configuration into plaintext logs can expose secrets. Impact depends on the secret privileges and consumer. Limit source access, separate values from output, and connect lifecycle to an operational inventory.
Assuming rotation and downstream acceptance occur together can break an old consumer or leave old versions unnecessarily valid. A source-current=b report alone cannot establish revoke=a. Obtain accepted/rejected metadata from the system enforcing revocation/expiry. Rejected alias a does not indicate compromise; it is the expected availability branch in this selected transition.
3. Blue · Secure development & defense
Read every scenario without motion
Effective snapshot
- The configuration-snapshot evidence was selected
Initial validInput carries public/"2" and revision cfg-a. Effective configuration is separately normalized to typed limit=2.
- Config observation
- Input cfg-a
- Snapshot correlation
- Effective snapshot not read
- Evidence scope
- No refresh outcome
- The source change was read separately
snapshotChange shows sourceRevisionAfter=cfg-b and sourceLimitAfter="3". Updated source text does not prove that the running snapshot changed.
- Config observation
- Source cfg-b / "3"
- Snapshot correlation
- Running snapshot under review
- Evidence scope
- No refresh outcome
- Running effective fields were compared
runningRevision remains cfg-a with runningLimit=2. Accepted source revision and process-consumption time are separate evidence fields.
- Config observation
- Source cfg-b / "3"
- Snapshot correlation
- Running cfg-a / 2
- Evidence scope
- No automatic refresh
- The new validated snapshot was kept separate
newValidatedRevision=cfg-b and newValidatedLimit=3 describe a separate outcome. Validation of this snapshot does not establish completed replacement of the old running process.
- Config observation
- New validated cfg-b / 3
- Snapshot correlation
- Running cfg-a / 2
- Evidence scope
- Replacement receipt not shown
- The selector sought a false-refresh claim
The selector seeks automaticallyRefreshed=true while source and effective revisions differ. The main XML gives 0 and a separate positive fixture gives 1; neither is a secret audit stream.
- Config observation
- Source/effective difference known
- Snapshot correlation
- Main count=0; positive=1
- Evidence scope
- Claim scope explicit
- The effective-state conclusion was not broadened
The fixture separates running cfg-a from validated cfg-b. It contains no actual environment scan, deployment or reload outcome for every consumer.
- Config observation
- Known: old running snapshot
- Snapshot correlation
- Known: new validated snapshot
- Evidence scope
- UNKNOWN: actual rollout
Observation gap
- The revision-observation scope was narrowed
This branch reviews a scope containing only source-revision information. It does not substitute source for running state when effective-consumer observations are missing.
- Config observation
- Source metadata only
- Snapshot correlation
- Consumer observation missing
- Evidence scope
- No refresh conclusion
- Required selector fields were separated
The selector requires the relationship among sourceRevision, effectiveRevision and automaticallyRefreshed. Source information alone cannot evaluate this predicate.
- Config observation
- Source metadata only
- Snapshot correlation
- Required consumer fields absent
- Evidence scope
- UNKNOWN: effective revision
- Missing and false remained distinct
Without the consumer element or required fields, no definite automaticallyRefreshed=false value is produced. Missing observation is neither a successful nor failed reload record.
- Config observation
- Source metadata only
- Snapshot correlation
- Unknown, not a false refresh value
- Evidence scope
- UNKNOWN: effective revision
- Zero matches were not treated as a clean rollout
Missing observations may produce no selector matches. Here count=0 does not prove that all consumers use cfg-b or that secret rotation completed.
- Config observation
- Source metadata only
- Snapshot correlation
- Selection coverage incomplete
- Evidence scope
- UNKNOWN: consumer update
- Benign metadata evidence was requested
Consumer role, effective revision and observation time are required. Exporting credential values or the entire environment is unnecessary for this narrow correlation.
- Config observation
- Source metadata only
- Snapshot correlation
- Effective metadata required
- Evidence scope
- No secret export needed
- The missing-evidence conclusion was preserved
The source change can be known while running consumption and downstream acceptance remain UNKNOWN. No outage or compromise cause is manufactured from this gap.
- Config observation
- Known: source metadata
- Snapshot correlation
- UNKNOWN: effective consumption
- Evidence scope
- UNKNOWN: downstream acceptance
IMPLEMENTATION · SECURITY CONTROL · VERIFICATION
Observe effective configuration without revealing values
Evaluate startup input against enum/type/required-field rules. Normal public/"2" normalizes to limit=2, while two rejects startup. Record accepted cfg-a separately from source cfg-b. Observe public mode and harmless limit fields without credentials. Missing-field observations do not automatically imply false or safe defaults.
Bind precedence and read timing to the service contract. For a startup snapshot, show that changing source environment does not refresh effective behavior; observe a new validated replacement/restart separately. Claims of process changes affecting parent or Worker copies need properly scoped evidence. Collect only needed harmless fields and revision metadata rather than real deployment environment dumps.
Track both owners of version transitions
Secret-source current alias, process-consumed alias, and downstream-accepted alias are different fields. Audit needs consumer role, outcome, version alias, and actual observation time without logging values. In the supplied current=b/process=a/accepted=b branch, rejection is explained by the old snapshot. Bind that conclusion to the downstream predicate rather than source-only rotation.
Verify the new version with its intended consumer and explicitly choose old-version acceptance and revocation ownership. Repairing dependency failure does not require giving everyone every secret: correct the selected consumer snapshot and permissions. Preserve the distinction between human-password and application-key rotation. This small metadata ledger does not prove a real vault encryption, access audit, or production rollout.
The artifact XPath selects automaticallyRefreshed=true claims when sourceRevision differs from effectiveRevision. A benign old snapshot yields 0; an incorrect refresh claim yields 1. This local XML check correlates source/current/effective fields and is not a secret-audit stream. A missing consumer element yielding0 remains insufficient evidence, not successful rotation.
NOW APPLY IT TO THE CASE
How do typing, snapshots and downstream acceptance differ?
Public configuration fields become a typed startup snapshot; secret-version aliases remain separate for source, consumer and accepted set.
Reconstruct decision order for input, server processing and response in the case. Parsed or valid data is not a completed operation; identify each owner and its condition.
Open the related case file ↗READ THE EXAMPLE TOGETHER
Configuration and version-consumption ledger
Select a field and examine what it supports and where the evidence ends.
Read the raw artifact and field explanations
{
"validationContract": {
"modeEnum": [
"public"
],
"limitDecimalInteger": true,
"educationalMin": 1,
"educationalMax": 10,
"precedence": "explicit supplied input only; no external env scan"
},
"validInput": {
"ATLAS_FIXTURE_MODE": "public",
"ATLAS_FIXTURE_LIMIT": "2",
"revision": "cfg-a"
},
"normalized": {
"mode": "public",
"limit": 2,
"revision": "cfg-a",
"immutableSnapshotSupplied": true
},
"invalidInput": {
"ATLAS_FIXTURE_MODE": "public",
"ATLAS_FIXTURE_LIMIT": "two",
"revision": "cfg-invalid",
"startupOutcome": "rejected",
"listening": false
},
"snapshotChange": {
"sourceRevisionBefore": "cfg-a",
"sourceRevisionAfter": "cfg-b",
"sourceLimitAfter": "3",
"runningRevision": "cfg-a",
"runningLimit": 2,
"newValidatedRevision": "cfg-b",
"newValidatedLimit": 3
},
"secretVersions": {
"aliasesAreCredentials": false,
"initialSource": "sec-ref-a",
"initialConsumer": "sec-ref-a",
"initialAccepted": [
"sec-ref-a"
],
"rotatedSource": "sec-ref-b",
"oldConsumer": "sec-ref-a",
"afterRevocationAccepted": [
"sec-ref-b"
],
"oldConsumerAccepted": false,
"newConsumer": "sec-ref-b",
"newConsumerAccepted": true,
"rotationImpliesRevocation": false,
"valueStoredInArtifact": false
},
"selector": {
"language": "XPath",
"xml": "<observations><consumer sourceRevision=\"cfg-b\" effectiveRevision=\"cfg-a\" automaticallyRefreshed=\"false\"/></observations>",
"xpath": "count(/observations/consumer[@sourceRevision!=@effectiveRevision and @automaticallyRefreshed=\"true\"])",
"expected": 0,
"positiveFixtureXml": "<observations><consumer sourceRevision=\"cfg-b\" effectiveRevision=\"cfg-a\" automaticallyRefreshed=\"true\"/></observations>",
"positiveExpected": 1,
"scope": "Only authored protocol-decision observations, not product log field names or a live HTTP capture.",
"missingFieldBehavior": "Missing observation is insufficient evidence; zero matches is not proof of correct runtime behavior."
}
}- validationContract / input
- Only explicit synthetic text input; range is educational.
- normalized / snapshotChange
- Typed accepted state differs from source metadata.
- secretVersions
- Noncredential aliases and an acceptance-lifecycle predicate.
Inert metadata without process.env inventory, real credentials, or vault responses. Validation and snapshot policy are application-specific.
Two reality checks
Environment variables make configuration typed and secret-safe.
Values can be text; type validation and secret delivery/protection require separate decisions.
Changing a source secret version refreshes every running consumer and revokes the old one.
Consumer snapshots, source rotation, and downstream revocation have different owners and transitions.
YOUR TURN
Work through this story.
Predict the outcome, find the evidence boundary, and explain it in your own words.
ATLAS_FIXTURE_LIMIT is the string two. Does selected startup open a listener?
- No; startup is rejected and listening=false.
- Yes; invalid config is silently trusted through a default.
Read the explained answer
No; startup is rejected and listening=false. — The contract requires a decimal integer 1–10; a word value is not converted into a valid normalized limit.
The source changed to cfg-b/limit=3. Why does the running process still show cfg-a/limit=2?
Selected lesson artifact fields; teaching example
- snapshotChange
- {"sourceRevisionBefore":"cfg-a","sourceRevisionAfter":"cfg-b","sourceLimitAfter":"3","runningRevision":"cfg-a","runningLimit":2,"newValidatedRevision":"cfg-b","newValidatedLimit":3}
- Editing the source immediately changes every process.env value.
- The running snapshot is immutable; an explicit validated reload/new process is required.
Read the explained answer
The running snapshot is immutable; an explicit validated reload/new process is required. — Changing the source does not automatically update consumer memory; newValidatedRevision is a different state.
The secret source rotated to sec-ref-b. Why are old-consumer revocation and new-consumer adoption separate conditions?
Read the explained answer
The source may publish a new version while a consumer retains an old reference. When the authority narrows the accepted set to b, oldConsumerAccepted=false; a new consumer must adopt b. Rotation alone is not revocation. These aliases contain no credential bytes; no real environment or secret store was read.
□ I distinguished rotation, adoption and revocation.
□ I did not count an alias as actual secret material.
Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples
Sources and scope
- Node.js v24.13.0 — Processprocess.env
- Node.js — Environment VariablesEnvironment Variables · process.env · DotEnv · Variable Values
- OWASP — Secrets Management Cheat Sheet1 Introduction · 2.3 Access Control · 2.6 Auditing · 2.7 Secret Lifecycle · 2.7.2 Rotation · 2.7.3 Revocation · 2.7.4 Expiration · 5.1 Injection of Secrets (file, in-memory) · 8.3 Detection lifecycle