State the Choice
Silence is not a default.
Overview
Where a setting has a safe answer and an unsafe answer, and the unsafe one is what happens by omission, the system refuses to run until someone states which it is.
Why
A default is a decision taken on behalf of someone who was not in the room. That is usually fine and occasionally catastrophic, because when the omitted answer is the unsafe one, silence produces exposure, and produces it quietly. It gets sharper when a system ships in more than one topology. Then there is often no default that is right for both, and choosing one means being quietly wrong for half of your deployments without telling them. The honest response is to refuse: fail the deploy, name the setting, and say why the answer cannot be guessed.
Standard
Classify every setting as safe to default, must be stated, or secret. A must-state setting has no default. Omitting it fails startup, with a message naming the setting, its valid values, and the reason the choice cannot be inferred. When configuration is ambiguous, refuse it rather than resolving toward the more permissive reading. A legacy value that could mean either the safe or the unsafe shape is rejected, not interpreted. Where an operator has spelled out an answer explicitly, the explicit answer wins over anything derived.
What This Forbids
- Defaults for security-relevant settings
- Resolving ambiguous configuration toward the more permissive interpretation
- A protection that an unset value silently disables
- "It works locally" as evidence that a default is fine
Examples
- Refusing to start in production until transport security for the database connection is stated. The driver does not negotiate encryption unless asked, and the system ships in two topologies, a private network and a managed remote instance, so neither default is correct for both.
- Rejecting a legacy single-container storage configuration outright rather than treating it as a fallback, because that fallback is precisely the exposure the newer split configuration exists to prevent.
- Proxy trust disabled by default, on the reasoning that a wrong "on" is materially worse than a missing value.
- A composition file that refuses to start on a known default password, using the orchestrator's own required-variable syntax rather than a documented warning.
Counter Examples
- Scaffolded configuration whose placeholder values pass shape validation, a placeholder address is still a valid address, so a deployment could reach production carrying the generator's own text. Shape validation is not a stated choice.
- One configuration surface typed, defaulted, validated and swept for placeholder text, while the other half of the same problem is read through bare accessors with per-call-site defaults and no schema, with a validation library sitting unused in the dependency list.
- A secret required at startup, scaffolded into every generated environment file, and read by no code anywhere. Requiring a value that does nothing trains operators to supply values without asking what they are for.
Lessons Learned
- When a system ships in two topologies, "the sensible default" is a fiction. There are two sensible defaults, and picking one means being quietly wrong for half your deployments.
- Failing a deploy is cheap. Failing a working day is not. The refusal is the feature.
- A refusal is only useful if it says what to do next. Name the setting, the valid values, and why the answer cannot be guessed, otherwise the gate becomes something people route around.
- This reflex appeared independently five times in one codebase before anyone noticed it was one idea. That recurrence is what promoted it from a habit to a principle.
Learned From
Related Principles· 2
Related Documents· 1
Referenced By· 6
Version History
- v0.1.0
Established after the same refusal pattern appeared independently five times in one codebase.