Skip to content

FIX: Type Safety, Environment Validation, Redis Integration Tests, an… - #413

Merged
meshackyaro merged 1 commit into
trustflow-protocol:mainfrom
Biokes:fix/type-safety-ci-improvements
Aug 31, 2026
Merged

FIX: Type Safety, Environment Validation, Redis Integration Tests, an…#413
meshackyaro merged 1 commit into
trustflow-protocol:mainfrom
Biokes:fix/type-safety-ci-improvements

Conversation

@Biokes

@Biokes Biokes commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

This PR addresses four related infrastructure and code quality improvements that strengthen the backend's type safety, configuration management, testing coverage, and security posture.

Closes #224
Closes #231
Closes #223
Closes #226


Summary of Changes

#224 — Enable TypeScript noImplicitAny and ESLint no-explicit-any

Problem: The codebase had noImplicitAny: false in tsconfig.json and no-explicit-any: "off" in .eslintrc.js, allowing implicit any types to slip through in request parsing, RPC response handling, and other critical paths where static typing provides the most value.

Solution:

  • Fixed all implicit/explicit any usages in production code:

    • health.controller.ts: Changed Promise<any> to Promise<HealthStatus>
    • event-processor.service.ts: Changed value: any to value: Record<string, unknown>
    • auth.guard.ts: Typed handleRequest signature to match Passport's base class
    • rate-limit.guard.ts: Created RateLimitRequest interface for type-safe request handling
    • event-ingestion.service.ts: Used xdr.ScVal and SorobanRpc.Server.GetEventsRequest types
    • soroban.helper.ts: Added proper type guard for SimulateTransactionResponse
    • stellar.service.ts: Used Horizon.HorizonApi.BalanceLine type
    • discord.service.ts: Added proper error type guard
    • metrics-http.interceptor.ts: Changed Observable<any> to Observable<unknown>
    • admin.guard.ts: Explicitly typed .map() callback parameter
  • Enabled strict compiler and lint checks:

    • Set noImplicitAny: true in tsconfig.json
    • Set @typescript-eslint/no-explicit-any: "warn" in .eslintrc.js
  • Added // eslint-disable-next-line comments to spec files where mocks legitimately use any (test-only suppressions)

Acceptance Criteria:

  • npx tsc --noEmit and npm run lint:check both pass with strict settings enabled
  • No behavior changes — types-only cleanup verified by existing test suite

#231 — Add Redis Integration Tests for Lua Scripts

Problem: Rate-limit and nonce-store specs mocked the Redis client rather than exercising the real Lua scripts (TOKEN_BUCKET_SCRIPT, ABUSE_LOCKOUT_SCRIPT, GETDEL_LUA) against an actual Redis server. Lua script bugs (syntax errors, incorrect KEYS/ARGV indexing) would only surface at runtime in production.

Solution:

  • CI already had a redis:7-alpine service container configured ✅
  • Created two new Redis integration test suites following the existing gig.service.redis-integration.spec.ts pattern:

backend/src/auth/nonce-store.redis-integration.spec.ts:

  • Tests GETDEL_LUA atomic get-and-delete script
  • Verifies TTL expiry, replay detection, NX semantics, and address isolation
  • Uses describeIfRedis pattern (skips when REDIS_URL unset for local dev)

backend/src/common/rate-limit/rate-limit.redis-integration.spec.ts:

  • Tests TOKEN_BUCKET_SCRIPT for token bucket refill and capacity management
  • Tests ABUSE_LOCKOUT_SCRIPT for sorted-set abuse tracking and lockout triggering
  • Verifies ZREMRANGEBYSCORE cleanup, IP vs wallet bucket independence, and state persistence across guard instances
  • Exercises time-based behaviors (refill, expiry, abuse window) with real delays

Acceptance Criteria:

  • CI spins up a real Redis instance and integration tests exercise actual Lua scripts
  • Local npm test runs are unaffected when REDIS_URL isn't set (tests skip gracefully)

#223 — Add Startup Environment Variable Validation with Zod

Problem: Configuration was read ad hoc with inline process.env.X || fallback scattered across many files. A typo'd variable name, empty string, or malformed value would silently fall through to a default or unusable value rather than failing at startup with a clear error.

Solution:

  • Created backend/src/config/env.config.ts with a centralized Zod schema for every environment variable the app reads:

    • Proper types: z.coerce.number(), z.string().url(), z.enum([...]), z.string().regex(...)
    • Format validation: JWT_SECRET min 16 chars, TRUSTFLOW_CONTRACT_ID contract address format
    • Required vs optional with defaults clearly documented
  • Added validateEnv() function called once at startup in main.ts:

    • Fails fast with a readable, aggregated error listing every invalid/missing variable
    • Caches the validated config in a typed object
  • Replaced scattered inline reads with typed config object imports across 13 files:

    • main.ts, auth.module.ts, jwt.strategy.ts, discord.service.ts, redis.module.ts
    • stellar.config.ts, rate-limit.guard.ts, event-ingestion.service.ts, soroban.helper.ts
    • health.service.ts, admin.guard.ts
  • Created comprehensive test suite (env.config.spec.ts) covering:

    • Missing required variables
    • Invalid formats (malformed URLs, wrong enum values, non-numeric ports)
    • Type coercion from string env vars to numbers
    • Production config validation

Acceptance Criteria:

  • App refuses to start with a clear, aggregated error message when required env vars are missing or malformed
  • Config reads go through one typed, validated source instead of scattered inline fallbacks
  • Test covers the failure path with intentionally broken env

#226 — Add npm audit Dependency Vulnerability Scanning to CI

Problem: CI had no automated signal when a known CVE landed in the dependency tree. With @stellar/stellar-sdk, ioredis, @sentry/node, and other dependencies pulling in a large transitive tree, vulnerabilities could go unnoticed until discovered manually.

Solution:

  • Added npm audit --audit-level=high step to .github/workflows/backend-ci.yml after the build step
  • The step runs against backend/package-lock.json dependency tree
  • Fails the build if high or critical vulnerabilities are found
  • Low and moderate findings are logged but don't block CI (balances security with practicality)
  • Includes clear inline documentation explaining the chosen threshold

Acceptance Criteria:

  • CI includes a dependency vulnerability scan step for the backend package tree
  • Failure behavior (blocks on high/critical) is documented in the workflow file

Testing

All changes are backward-compatible and have been verified to:

  • Pass TypeScript compilation with noImplicitAny: true
  • Pass ESLint with no-explicit-any: "warn"
  • Maintain existing test suite coverage (no behavior changes)
  • Add new Redis integration test coverage for Lua scripts
  • Add environment validation test coverage

The Redis integration tests will run in CI against the existing redis:7-alpine service container and skip gracefully in local environments without REDIS_URL.


Migration Notes

Environment Variables:
After merging, the app will fail to start if JWT_SECRET is not set or is shorter than 16 characters. Ensure your .env file or deployment environment includes:

JWT_SECRET=your-secret-at-least-16-chars

All other environment variables have sensible defaults and are optional. If any required variable is missing or malformed, the startup error message will list exactly which variables need to be fixed.


Files Changed

Configuration & Core:

  • .github/workflows/backend-ci.yml — Added npm audit step
  • backend/tsconfig.json — Enabled noImplicitAny
  • backend/.eslintrc.js — Enabled no-explicit-any: "warn"
  • backend/src/config/env.config.ts — New centralized env validation (NEW)
  • backend/src/config/env.config.spec.ts — Env validation tests (NEW)
  • backend/src/main.ts — Added env validation at startup, replaced inline reads

Type Safety Fixes:

  • backend/src/monitoring/health.controller.ts
  • backend/src/event-ingestion/event-processor.service.ts
  • backend/src/auth/auth.guard.ts
  • backend/src/common/rate-limit/rate-limit.guard.ts
  • backend/src/event-ingestion/event-ingestion.service.ts
  • backend/src/stellar/soroban.helper.ts
  • backend/src/stellar/stellar.service.ts
  • backend/src/webhook/discord.service.ts
  • backend/src/monitoring/metrics-http.interceptor.ts
  • backend/src/admin/admin.guard.ts

Config Migration:

  • backend/src/auth/auth.module.ts
  • backend/src/auth/jwt.strategy.ts
  • backend/src/common/redis/redis.module.ts
  • backend/src/stellar/stellar.config.ts
  • backend/src/monitoring/health.service.ts

Redis Integration Tests (NEW):

  • backend/src/auth/nonce-store.redis-integration.spec.ts
  • backend/src/common/rate-limit/rate-limit.redis-integration.spec.ts

Test Updates:

  • backend/src/auth/nonce-store.service.spec.ts
  • backend/src/common/rate-limit/rate-limit.guard.spec.ts
  • backend/src/auth/auth.service.spec.ts
  • backend/src/auth/auth.controller.spec.ts
  • backend/src/ipfs-pinning/ipfs-pinning.e2e-spec.ts

Checklist

  • All four issues addressed and acceptance criteria met
  • No behavior changes — types and config only
  • Existing test suite continues to pass
  • New Redis integration tests added
  • New environment validation tests added
  • Clear startup error messages for configuration issues
  • CI includes dependency vulnerability scanning

@Biokes
Biokes requested a review from meshackyaro as a code owner August 31, 2026 07:32
@drips-wave

drips-wave Bot commented Aug 31, 2026

Copy link
Copy Markdown

@Biokes Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@meshackyaro
meshackyaro merged commit 90fd2f7 into trustflow-protocol:main Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants