mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
chore(server): forbid direct process.env access outside app-config
This commit is contained in:
@@ -44,4 +44,35 @@ export default tseslint.config(
|
||||
'prefer-const': 'warn',
|
||||
},
|
||||
},
|
||||
{
|
||||
// Config-access guard: every env read in src/ goes through src/app-config
|
||||
// (readEnv() / derive functions / registerAs tokens). Direct process.env
|
||||
// access is banned outside the documented exemptions below — see
|
||||
// src/app-config/README.md for the rationale behind each.
|
||||
files: ['src/**/*.ts'],
|
||||
ignores: [
|
||||
// The config layer itself.
|
||||
'src/app-config/**',
|
||||
'src/nest/app-config/**',
|
||||
// Key-material resolution (file persistence + runtime rotation), not env config.
|
||||
'src/config.ts',
|
||||
// Scrubbed plugin child process — must not import app-config.
|
||||
'src/nest/plugins/runtime/plugin-host-entry.ts',
|
||||
// Child-env whitelist block: the env there is an IPC channel to the sandbox.
|
||||
'src/nest/plugins/supervisor/plugin-supervisor.ts',
|
||||
// Dynamic-key caps (process.env[name] with a computed name).
|
||||
'src/nest/plugins/host/daily-budget.ts',
|
||||
'src/nest/plugins/host/plugin-audit.ts',
|
||||
],
|
||||
rules: {
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
{
|
||||
selector: "MemberExpression[object.name='process'][property.name='env']",
|
||||
message:
|
||||
'Read configuration via src/app-config (readEnv()/derive/tokens), not process.env. Exemptions: eslint.config.mjs + src/app-config/README.md.',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
@@ -74,3 +74,19 @@ ADMIN_PASSWORD, IDEMPOTENCY_TTL_SECONDS, MCP_RATE_LIMIT (request-path check).
|
||||
- `src/config.ts` ENCRYPTION_KEY/JWT_SECRET resolution — key material with file
|
||||
persistence and runtime rotation, not env config.
|
||||
- Standalone scripts (`reset-admin.js`, `scripts/*`) and `tests/**`.
|
||||
|
||||
The exemption list is enforced by the `no-restricted-syntax` ban on
|
||||
`process.env` in `eslint.config.mjs` — keep the two lists in sync.
|
||||
|
||||
## Follow-up candidates (quirks pinned during the migration, deliberately NOT fixed)
|
||||
|
||||
- `numberOr` (`Number(x) || d`) treats `"0"` and negative-invalid values oddly:
|
||||
`PORT=0` silently becomes 3001, `TREK_PLUGIN_RPC_BURST=-5` stays -5.
|
||||
- `TRUST_PROXY=0` resolves to 1 hop (`parseInt || 1`).
|
||||
- APP_URL trailing-slash stripping differs per site (feeds strips one slash,
|
||||
notifications strips all).
|
||||
- `DEMO_ADMIN_EMAIL` defaults differ (demo-seed: admin@trek.app, demo-reset:
|
||||
admin@nomad.app).
|
||||
- NODE_ENV comparisons are case-sensitive at some sites (HSTS activation,
|
||||
platform statics, spa-fallback, authService dev_mode, oidcService
|
||||
frontendUrl) and case-insensitive at others.
|
||||
|
||||
@@ -33,6 +33,12 @@ mount to Nest and leaves the sibling trip routes (days, places, ...) on Express.
|
||||
client's `X-Idempotency-Key` on mutations, mirroring the legacy
|
||||
`applyIdempotency` middleware so retried writes don't double-apply.
|
||||
- `strangler.ts` — supports both static prefixes and `:param` pattern prefixes.
|
||||
- `app-config/` — the `@nestjs/config` binding (`AppConfigModule`, global). Never
|
||||
read `process.env` in a module (ESLint enforces this): inject a boot-stable
|
||||
namespace via its `registerAs` token (`@Inject(mcpConfig.KEY) … ConfigType<…>`)
|
||||
or read runtime-toggled values live through `RuntimeEnvService` / `readEnv()`
|
||||
from `src/app-config`. The classification and invariants live in
|
||||
`src/app-config/README.md`.
|
||||
|
||||
## Parity gotchas worth remembering
|
||||
|
||||
|
||||
Reference in New Issue
Block a user