Add fail-fast configuration validation and standalone typecheck (#230) - #237
Open
Paranoa-dev wants to merge 1 commit into
Open
Add fail-fast configuration validation and standalone typecheck (#230)#237Paranoa-dev wants to merge 1 commit into
Paranoa-dev wants to merge 1 commit into
Conversation
…rg#230) - validateConfig() enforces required values before the server binds: API_KEY required in production, PORT valid 1-65535, non-negative rate-limit/idempotency values; warns loudly (non-prod) on open access. - Wire validateConfig into createApp/getConfig in app.ts. - Add typecheck script (tsc --noEmit) and a distinct CI Typecheck step. - Extend config.test.ts with a validateConfig suite. closes AnchorNet-Org#230
Paranoa-dev
marked this pull request as ready for review
August 26, 2026 10:09
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.
Add fail-fast configuration validation and a standalone
typecheckstep (#230)Summary
This PR defines and enforces the AnchorNet-Backend configuration contract:
validateConfig()runs before the server binds aport (via
getConfig()/createApp()insrc/app.ts). It throws aConfigValidationErrorwhen a required value is missing or invalid, instead ofbooting into a silently broken or insecure state.
typecheckscript (tsc --noEmit) that is distinct frombuild(which emits
dist/), wired into CI as its own step.The goal of #230 is the configuration contract only. The API-key auth policy (what
a missing key means at runtime) stays owned by
apiKeyAuth; this PR only decidesthat a missing key is unacceptable in production and fails fast there.
Configuration inventory
portPORT30013001feeBpsFEE_BPS100–10000)apiKeyAPI_KEYapiKeyAuthis a no-op → open mutating access. Required inproduction(fail-fast).corsOriginsCORS_ORIGINbodyLimitBODY_LIMIT"100kb"maintenanceModeMAINTENANCE_MODEfalseenvNODE_ENV"development"developmentdefaultsmetricsSnapshotIntervalMsMETRICS_SNAPSHOT_INTERVAL_MSidempotencyTtlMsIDEMPOTENCY_TTL_MS86_400_000rateLimitMaxRATE_LIMIT_MAX30rateLimitWindowMsRATE_LIMIT_WINDOW_MS60_000trustProxyTRUST_PROXYfalseX-Forwarded-*Required vs optional decision
Kept deliberately conservative — only values whose absence changes a security posture
or makes the server undeliverable are required:
API_KEYwhenNODE_ENV=production. Without it the auth middleware degrades to ano-op (open mutating access); we refuse to start rather than silently downgrade
security. This closes the fail-open gap for production, called out explicitly so it
does not surprise existing deployments (dev/test are unaffected).
PORTmust be a valid TCP port (1–65535); an invalid port makes the serverundeliverable.
RATE_LIMIT_MAX >= 0,IDEMPOTENCY_TTL_MS >= 0.its default changed by this PR.
When a key is unset in a non-production environment, the service still starts (dev
convenience) but emits a loud
console.warnthat it is running with open mutatingaccess. The warning is suppressed under
NODE_ENV=testto keep test output clean.Why hand-written validation?
Validation is implemented directly in
src/config.tsrather than via a schema library(e.g. zod). The project intentionally keeps a lean dependency footprint (3 runtime
deps). The checks are small, reviewable, and add no runtime dependency. If the team
prefers a schema-driven approach later, swapping the internals of
validateConfigislocalised to this file.
typecheckscript + CIpackage.json: added"typecheck": "tsc --noEmit"(separate frombuild, whichemits
dist/)..github/workflows/ci.yml: added a dedicated Typecheck step between Lint andBuild so type errors are surfaced independently of the emit build.
Test plan
src/config.test.tsextended with avalidateConfigsuite:API_KEYrequired + throws inproduction, allowed indevelopment/test;PORTthrows;RATE_LIMIT_MAXandIDEMPOTENCY_TTL_MSthrow.npm run typecheck,npm run lint, andnpm test(497 tests) all pass.closes #230