feat(config): fail-fast validation + standalone typecheck script (#230) - #231
Open
Paranoa-dev wants to merge 1 commit into
Open
feat(config): fail-fast validation + standalone typecheck script (#230)#231Paranoa-dev wants to merge 1 commit into
Paranoa-dev wants to merge 1 commit into
Conversation
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.
Fail-fast configuration validation + standalone
typecheckscript (#230)Resolves #230 (GrantFox OSS / Third Campaign).
Summary
package.jsonhad no standalonetypecheck— types were only checked as aside effect of
build. More importantly, configuration failures degradedsilently:
src/middleware/apiKeyAuth.tsmakes the auth middleware a no-op(open access) whenever
API_KEYis unset, so a missing environment variablechanged the service's security posture instead of refusing to start.
This PR adds a fail-fast configuration contract (
validateConfig) that runs atstartup before the port binds, a
typecheckscript wired into CI as a stepdistinct from
build, the full configuration inventory, and tests for therequired-value failure path.
Configuration inventory
PORT30013001FEE_BPS100–10000API_KEYproduction; optional in dev/testproduction: refuses to start namingAPI_KEYCORS_ORIGINBODY_LIMIT"100kb"MAINTENANCE_MODEfalseNODE_ENV"development"METRICS_SNAPSHOT_INTERVAL_MSIDEMPOTENCY_TTL_MS86_400_000RATE_LIMIT_MAX30RATE_LIMIT_WINDOW_MS60_000TRUST_PROXYfalse(Full reasoning in
docs/CONFIGURATION.md.)Required-vs-optional classification
API_KEY→ required inproductiononly. Its absence silently disablesauth on every mutating endpoint — a security-relevant fail-open — so it must
be present in production. In
development/testthe historical open accessis preserved (no secret needed for local runs).
control when absent.
FEE_BPSis range-validated but still optional.Environment-sensitivity policy
Requirements are
NODE_ENV-driven, never an unset variable:production⇒API_KEYmandatory;development/test⇒API_KEYoptional. The mechanismis explicit and centralised in
validateConfig.Validation approach
Hand-written checks in
src/config.ts— no new dependency. The serviceships exactly three runtime deps; a schema-validation library would be
unjustified for a twelve-value config that already has parsing helpers.
validateConfigis invoked fromloadConfig, so it runs once at startupbefore the server binds a port. Failures are actionable: the thrown
ConfigValidationErrornames the offending variable and explains the fix.Deliberate fail-open closure (called out)
The only behaviour change vs. the previous release: a
productiondeploymentwithout
API_KEYnow refuses to start instead of running with openmutating endpoints. No default was changed.
Coordination with the
apiKeyAuthissueThis issue owns the general configuration contract (fail fast on a missing
required value). The concrete authentication policy (when/how
API_KEYisenforced on routes) is owned by the separate
apiKeyAuthissue.Evidence — fail-fast at startup
What changed
src/config.ts— addedvalidateConfig()+ConfigValidationError; calledfrom
loadConfigso validation runs before the port binds.src/index.ts— wraps startup so an invalid configuration exits non-zerowith a clear message before binding; keeps the default
appexport fortests.
src/config.test.ts— addedvalidateConfigtests: production-without-API_KEYthrows (
ConfigValidationError, namesAPI_KEY), blank key treated as unset,dev/test allow missing key, production-with-key passes.
package.json— added"typecheck": "tsc --noEmit"..github/workflows/ci.yml— added a distinct Type check step (runsbefore
build).docs/CONFIGURATION.md— full inventory, classification, and policy.Acceptance criteria (from #230)
typecheckscript exists and runs in CI as a separate step frombuild.npm run lint,npm run typecheck,npm run buildandnpm testall pass (494 tests, 42 suites).Verification
Closes #230.