Skip to content

refactor: migrate environment variable access to appConfig…#1801

Merged
Artuomka merged 1 commit into
mainfrom
backend_config
May 26, 2026
Merged

refactor: migrate environment variable access to appConfig…#1801
Artuomka merged 1 commit into
mainfrom
backend_config

Conversation

@Artuomka
Copy link
Copy Markdown
Collaborator

@Artuomka Artuomka commented May 26, 2026

…for improved configuration management

  • Introduced appConfig to centralize configuration management and replace direct process.env access.
  • Updated various services and utilities to utilize appConfig for retrieving configuration values.
  • Removed deprecated helper functions for environment variable access.
  • Enhanced test environment handling by utilizing isTest() method from appConfig.
  • Ensured all database connection configurations are now sourced from appConfig.
  • Improved readability and maintainability of the codebase by consolidating configuration logic.

Summary by CodeRabbit

  • Refactor
    • Centralized configuration management system for environment-based settings across the backend, replacing scattered environment variable access patterns with a unified configuration service.
    • Improved test environment detection through a dedicated helper function.
    • Removed legacy configuration and environment variable utility functions in favor of the new centralized approach.

…ed configuration management

- Introduced appConfig to centralize configuration management and replace direct process.env access.
- Updated various services and utilities to utilize appConfig for retrieving configuration values.
- Removed deprecated helper functions for environment variable access.
- Enhanced test environment handling by utilizing isTest() method from appConfig.
- Ensured all database connection configurations are now sourced from appConfig.
- Improved readability and maintainability of the codebase by consolidating configuration logic.
Copilot AI review requested due to automatic review settings May 26, 2026 08:20
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 26, 2026

📝 Walkthrough

Walkthrough

This PR migrates the backend from scattered process.env reads to a centralized AppConfig configuration system. A new AppConfig class freezes configuration objects at application startup, sourced from environment variables. All middleware, services, helpers, and application logic are updated to read from the shared appConfig singleton instead of directly accessing environment variables. The refactoring also replaces direct process.env.NODE_ENV checks with a centralized isTest() helper function that delegates to appConfig.

Changes

Centralized Configuration System Refactoring

Layer / File(s) Summary
Centralized configuration infrastructure
backend/src/shared/config/app-config.ts
New AppConfig class with typed interfaces (AuthConfig, AppSectionConfig, DbConfig, EmailConfig, ThirdPartyConfig, TestDbConfig) reads from process.env, freezes config objects, and exposes isTest, isSaaS, validate(), and getTypeOrmConfig(). Supports both PGlite and standard Postgres database modes.
NestJS module and ConfigService refactoring
backend/src/shared/config/config.module.ts, config.service.ts
New global ConfigModule validates and provides ConfigService. ConfigService refactored into thin delegation wrapper that exposes appConfig properties as getters and delegates validate() and getTypeOrmConfig() to appConfig.
Helper functions
backend/src/helpers/app/is-test.ts, is-saas.ts
isTest() and isSaaS() helpers refactored to read from appConfig instead of environment variables. Removed obsolete environment-variable accessor and validation functions.
Application module and bootstrap
backend/src/app.module.ts, main.ts
ApplicationModule imports global ConfigModule. Bootstrap validates via appConfig.validate() and derives Sentry DSN and global prefix from appConfig instead of environment variables.
Authentication middleware
backend/src/authorization/*.middleware.ts
Six middleware files (auth, auth-with-api, basic-auth, non-scoped-auth, saas-auth, temporary-auth) updated to read JWT secrets and Basic auth credentials from appConfig.auth instead of process.env. Test-mode detection replaced with isTest() helper.
Third-party service configuration
backend/src/entities/amplitude/amplitude.service.ts, backend/src/helpers/slack/slack-post-message.ts, backend/src/shared/services/turnstile.service.ts
Services read API keys (Amplitude, Slack, Turnstile) from appConfig.thirdParty instead of environment variables. isTest() used to conditionally skip analytics/notifications in test environments.
Core services and encryption
backend/src/entities/email/email-config/email-config.service.ts, backend/src/entities/email/email/email.service.ts, backend/src/entities/logging/winston-logger.ts, backend/src/helpers/encryption/encryptor.ts
Email service constructs config from appConfig.email. Winston logger reads logLevel from appConfig.app. Encryptor reads keys from appConfig.auth and appConfig.thirdParty.
Constants and test database configuration
backend/src/helpers/constants/constants.ts
Test connection parameters for Postgres, MSSQL, Oracle, MySQL, MongoDB, and DB2 now read from appConfig.testDb instead of environment variables. isSaaS() and isTest() helpers replace direct env checks.
User utilities
backend/src/entities/user/utils/generate-gwt-token.ts, get-cookie-domain-options.ts
JWT token generation utilities and cookie domain resolution read secrets/domain from appConfig instead of environment variables.
Connection entity and validation
backend/src/entities/connection/connection.entity.ts, backend/src/entities/connection/utils/is-host-allowed.ts, validate-create-connection-data.ts
Entity and validation logic uses isTest() for test-mode detection when setting signing keys and gating SSH/host validation.
Agent and AI logic
backend/src/entities/agent/repository/custom-agent-repository-extension.ts, backend/src/entities/ai/user-ai-requests-v2.controller.ts
Agent token generation and AI controller timeout decorators use isTest() instead of environment checks for test vs. production behavior selection.
Company info and table action validation
backend/src/entities/company-info/company-info-helper.service.ts, use-cases/invite-user-in-company.use.case.ts, backend/src/entities/table-actions/table-action-rules-module/application/dto/create-action-rules-with-actions-and-events-body.dto.ts, use-cases/create-action-rule.use.case.ts, use-cases/update-action-rule-with-actions-and-events.use.case.ts
Services and use cases use isTest() for conditional validation gating. URL validators skip format checks in test environments.
Table retrieval and persistence
backend/src/entities/table/use-cases/find-tables-in-connection.use.case.ts, find-tables-in-connection-v2.use.case.ts, backend/src/entities/table-schema/utils/dynamodb-schema-op.ts, backend/src/helpers/validators/validation-helper.ts, backend/src/interceptors/timeout.interceptor.ts, backend/src/shared/database/database.service.ts
Use cases gate table-info persistence on isTest(). DynamoDB client, password validation, timeout interceptor, and database service all use isTest() instead of environment checks.
SaaS microservice JWT
backend/src/microservices/gateways/saas-gateway.ts/base-saas-gateway.service.ts, utils/generate-saas-jwt.ts
SaaS gateway and JWT generation utilities read microservice JWT secret and base URL from appConfig.auth and appConfig.thirdParty instead of environment variables.

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

  • rocket-admin/rocketadmin#1686: Modifies custom-agent-repository-extension.ts in the token generation path that is refactored in this PR to use isTest().
  • rocket-admin/rocketadmin#1719: Adds new SaaS endpoint that depends on the refactored SaaSAuthMiddleware JWT verification using appConfig.auth.microserviceJwtSecret.
  • rocket-admin/rocketadmin#1687: Refactors table retrieval use cases that this PR updates to use isTest() for persistence gating.

Suggested reviewers

  • lyubov-voloshko

Poem

A rabbit hops through config refactored,
From scattered process.env shores,
To appConfig centrally chartered,
Where secrets freeze in frozen stores. 🐰✨
Middleware and services dance in harmony,
With isTest() bounding free!

🚥 Pre-merge checks | ✅ 4 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Security Check ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately summarizes the main change: migrating environment variable access to a centralized appConfig object across the codebase.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch backend_config

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR centralizes environment-based configuration into a single appConfig module and migrates scattered process.env access (and related helpers) to that shared configuration layer, improving consistency across services/middlewares and simplifying validation/TypeORM setup.

Changes:

  • Added AppConfig (appConfig) + global ConfigModule/ConfigService wrapper to provide typed, centralized configuration and validation.
  • Migrated many services, middlewares, and utilities from direct process.env reads to appConfig / isTest() / isSaaS().
  • Removed deprecated env helper/validator utilities (get-process-variable, get-requeired-env-variable, required-environment-variables.validator).

Reviewed changes

Copilot reviewed 45 out of 45 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
backend/src/shared/services/turnstile.service.ts Uses appConfig for Turnstile secret instead of process.env.
backend/src/shared/database/database.service.ts Switches test-environment check to isTest().
backend/src/shared/config/config.service.ts Replaced old dotenv-based config service with getters over appConfig.
backend/src/shared/config/config.module.ts Introduces global ConfigModule that validates config on initialization.
backend/src/shared/config/app-config.ts Adds centralized config reader/validator + TypeORM config builder.
backend/src/microservices/gateways/saas-gateway.ts/utils/generate-saas-jwt.ts Reads microservice JWT secret from appConfig with explicit missing-secret error.
backend/src/microservices/gateways/saas-gateway.ts/base-saas-gateway.service.ts Uses appConfig for SaaS base URL defaulting.
backend/src/main.ts Validates required config via appConfig.validate() and uses config-backed values for Sentry/global prefix.
backend/src/interceptors/timeout.interceptor.ts Uses isTest() to pick default timeout values.
backend/src/helpers/validators/validation-helper.ts Uses isTest() to relax password strength in tests.
backend/src/helpers/validators/required-environment-variables.validator.ts Removed in favor of appConfig.validate().
backend/src/helpers/validators/is-action-url-host-allowed.ts Uses isTest() to bypass host checks in tests.
backend/src/helpers/slack/slack-post-message.ts Reads Slack token and test flag from appConfig.
backend/src/helpers/get-process-variable.ts Removed deprecated env accessor helper.
backend/src/helpers/encryption/encryptor.ts Reads private key / intercom key from appConfig.
backend/src/helpers/constants/constants.ts Migrates test-connection config + app domain address to appConfig; simplifies SaaS gating.
backend/src/helpers/app/is-test.ts Implements isTest() via appConfig.
backend/src/helpers/app/is-saas.ts Implements isSaaS() via appConfig.
backend/src/helpers/app/get-requeired-env-variable.ts Removed deprecated required-env helper.
backend/src/entities/user/utils/get-cookie-domain-options.ts Reads cookie domain from appConfig.
backend/src/entities/user/utils/generate-gwt-token.ts Reads JWT secrets from appConfig.
backend/src/entities/table/use-cases/find-tables-in-connection.use.case.ts Uses isTest() to gate side-effect saving table info.
backend/src/entities/table/use-cases/find-tables-in-connection-v2.use.case.ts Uses isTest() similarly; minor formatting changes.
backend/src/entities/table-schema/utils/dynamodb-schema-op.ts Uses isTest() for DynamoDB region override in tests.
backend/src/entities/table-actions/table-action-rules-module/use-cases/update-action-rule-with-actions-and-events.use.case.ts Uses isTest() to relax URL validation in tests.
backend/src/entities/table-actions/table-action-rules-module/use-cases/create-action-rule.use.case.ts Uses isTest() to relax URL validation in tests.
backend/src/entities/table-actions/table-action-rules-module/application/dto/create-action-rules-with-actions-and-events-body.dto.ts Uses isTest() to conditionally apply IsUrl.
backend/src/entities/logging/winston-logger.ts Reads log level from appConfig.
backend/src/entities/email/email/email.service.ts Uses appConfig for “from” address; isTest() to skip sending in tests.
backend/src/entities/email/email-config/email-config.service.ts Uses appConfig for SMTP config resolution.
backend/src/entities/connection/utils/validate-create-connection-data.ts Uses isTest() to alter host/type validation behavior in tests.
backend/src/entities/connection/utils/is-host-allowed.ts Uses isTest() in allow/deny logic.
backend/src/entities/connection/connection.entity.ts Uses isTest() to set deterministic signing key in tests.
backend/src/entities/company-info/use-cases/invite-user-in-company.use.case.ts Uses isTest() to expose verification string in tests.
backend/src/entities/company-info/company-info-helper.service.ts Uses isTest() to bypass SaaS invitation limits in tests.
backend/src/entities/amplitude/amplitude.service.ts Reads Amplitude key from appConfig; skips in tests via isTest().
backend/src/entities/ai/user-ai-requests-v2.controller.ts Uses isTest() to set AI endpoint timeouts.
backend/src/entities/agent/repository/custom-agent-repository-extension.ts Uses isTest() for test token behavior.
backend/src/authorization/temporary-auth.middleware.ts Uses isTest() for test bypass; reads JWT secret from appConfig.
backend/src/authorization/saas-auth.middleware.ts Reads microservice JWT secret from appConfig.
backend/src/authorization/non-scoped-auth.middleware.ts Uses isTest() for test bypass; reads JWT secret from appConfig.
backend/src/authorization/basic-auth.middleware.ts Reads basic auth creds from appConfig.
backend/src/authorization/auth.middleware.ts Uses isTest() for test bypass; reads JWT secret from appConfig.
backend/src/authorization/auth-with-api.middleware.ts Reads JWT secret from appConfig.
backend/src/app.module.ts Registers global ConfigModule in the main module imports.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +236 to +242
public get isTest(): boolean {
return process.env.NODE_ENV === 'test';
}

public get isSaaS(): boolean {
return !!process.env.IS_SAAS;
}
Comment on lines +161 to +168
this.email = Object.freeze({
configString: readString('EMAIL_CONFIG_STRING'),
host: readString('EMAIL_SERVICE_HOST'),
port: readInt('EMAIL_SERVICE_PORT') ?? DEFAULT_EMAIL_PORT,
username: readString('EMAIL_SERVICE_USERNAME'),
password: readString('EMAIL_SERVICE_PASSWORD'),
nonSecure: readString('NON_SSL_EMAIL') === null,
from: readString('EMAIL_FROM') ?? AUTOADMIN_SUPPORT_MAIL,
port: emailServicePort,
host: host,
port: port,
secure: nonSecure,
Comment on lines +268 to +271
? path.join(process.cwd(), ...pgLiteFolderPath.split('/'))
: path.join(__dirname, '..', '..', '..', pgLiteFolderPath);
console.info('\nPg Lite Folder Patch: ', pgLiteFolderPath, '\n');
const resolvedPath = path.resolve(fullPath);
@Artuomka Artuomka enabled auto-merge May 26, 2026 08:26
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
backend/src/shared/config/config.module.ts (1)

10-14: ⚡ Quick win

Annotate useFactory return type explicitly.

Please add an explicit return type on the factory callback to match the TypeScript typing guideline.

♻️ Proposed change
-			useFactory: () => {
+			useFactory: (): ConfigService => {
 				const service = new ConfigService();
 				appConfig.validate();
 				return service;
 			},

As per coding guidelines, "Always add type annotations to function parameters and return types in TypeScript".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/shared/config/config.module.ts` around lines 10 - 14, The factory
callback for the Nest provider lacks an explicit return type; update the
useFactory declaration to explicitly return the ConfigService type (i.e.,
annotate the callback as returning ConfigService) so the function signature for
useFactory: () => ConfigService matches TypeScript guidelines and the created
instance from new ConfigService() and appConfig.validate() is correctly typed.
backend/src/entities/table-actions/table-action-rules-module/application/dto/create-action-rules-with-actions-and-events-body.dto.ts (1)

23-31: ⚡ Quick win

Add explicit return type to IsUrlIfNotTest.

IsUrlIfNotTest currently relies on inference. Please annotate the return type explicitly for consistency and stronger contracts.

♻️ Proposed change
-function IsUrlIfNotTest(validationOptions?: IsURLOptions) {
-	return (object: NonNullable<unknown>, propertyName: string) => {
+function IsUrlIfNotTest(validationOptions?: IsURLOptions): PropertyDecorator {
+	return (object: object, propertyName: string | symbol): void => {
 		const decorators = [IsString()];
 		if (!isTest()) {
 			decorators.push(IsUrl(validationOptions));
 		}
 		applyDecorators(...decorators)(object, propertyName);
 	};
 }

As per coding guidelines, "Always add type annotations to function parameters and return types in TypeScript".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@backend/src/entities/table-actions/table-action-rules-module/application/dto/create-action-rules-with-actions-and-events-body.dto.ts`
around lines 23 - 31, The function IsUrlIfNotTest lacks an explicit return type;
change its signature to declare the decorator return type (e.g. add :
PropertyDecorator) so the compiler knows it returns a property decorator. Update
the declaration to function IsUrlIfNotTest(validationOptions?: IsURLOptions):
PropertyDecorator { ... } (the inner function can remain as-is and continue
calling applyDecorators with IsString and conditional IsUrl).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/entities/email/email/email.service.ts`:
- Line 38: The test-mode guard currently does "if (isTest()) return;" which
returns undefined but callers expect null for "no mail sent"; change that branch
to "if (isTest()) return null;" so the method in email.service.ts (the isTest()
check inside the email sending method) returns null explicitly in test mode to
match the method contract and avoid breaking null-only checks.

In `@backend/src/helpers/slack/slack-post-message.ts`:
- Line 8: The guard currently uses appConfig.isTest (a function reference) which
always evaluates truthy; change the condition to call the function (use
appConfig.isTest()) so the short-circuit only happens when tests are actually
detected or when slackBotToken is missing; update the conditional in
slack-post-message.ts (the if that references appConfig.isTest and
slackBotToken) to use appConfig.isTest() while preserving the existing ||
!slackBotToken logic.

In `@backend/src/shared/config/app-config.ts`:
- Line 270: Fix the typo in the console.info message: update the console.info
call that logs pgLiteFolderPath (the console.info('\nPg Lite Folder Patch: ',
pgLiteFolderPath, '\n') statement) to say "Path" instead of "Patch" so the log
reads "Pg Lite Folder Path: " while leaving pgLiteFolderPath and surrounding
formatting unchanged.
- Line 167: The nonSecure flag is inverted: currently nonSecure is true when
readString('NON_SSL_EMAIL') === null; change the logic so nonSecure reflects the
presence of the env var by setting nonSecure to a truthy check of the env value
(e.g., nonSecure: !!readString('NON_SSL_EMAIL') or nonSecure:
readString('NON_SSL_EMAIL') !== null) so that when NON_SSL_EMAIL is set,
nonSecure becomes true; update the property in the same config object where
nonSecure is defined to use this corrected condition.
- Around line 324-342: The parseTypeORMUrl function uses parse.parse() (from
parse) which can return nullable fields and currently types ssl as any; update
the return type to be strict (e.g., ssl: boolean | undefined or a specific SSL
config type) and defensively handle nullable parse results from parse.parse(url)
by checking for null/undefined for host, port, user, password, database and
providing safe defaults or throwing a clear error; ensure port is converted with
Number(...) or conditional parseInt only when port is a string and fall back to
a default number or undefined to match the return type; reference
parseTypeORMUrl and parse.parse in your changes.

---

Nitpick comments:
In
`@backend/src/entities/table-actions/table-action-rules-module/application/dto/create-action-rules-with-actions-and-events-body.dto.ts`:
- Around line 23-31: The function IsUrlIfNotTest lacks an explicit return type;
change its signature to declare the decorator return type (e.g. add :
PropertyDecorator) so the compiler knows it returns a property decorator. Update
the declaration to function IsUrlIfNotTest(validationOptions?: IsURLOptions):
PropertyDecorator { ... } (the inner function can remain as-is and continue
calling applyDecorators with IsString and conditional IsUrl).

In `@backend/src/shared/config/config.module.ts`:
- Around line 10-14: The factory callback for the Nest provider lacks an
explicit return type; update the useFactory declaration to explicitly return the
ConfigService type (i.e., annotate the callback as returning ConfigService) so
the function signature for useFactory: () => ConfigService matches TypeScript
guidelines and the created instance from new ConfigService() and
appConfig.validate() is correctly typed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6cb0a464-bd93-4092-971a-1f9af9565d7f

📥 Commits

Reviewing files that changed from the base of the PR and between f80c6a0 and 8cc7383.

📒 Files selected for processing (45)
  • backend/src/app.module.ts
  • backend/src/authorization/auth-with-api.middleware.ts
  • backend/src/authorization/auth.middleware.ts
  • backend/src/authorization/basic-auth.middleware.ts
  • backend/src/authorization/non-scoped-auth.middleware.ts
  • backend/src/authorization/saas-auth.middleware.ts
  • backend/src/authorization/temporary-auth.middleware.ts
  • backend/src/entities/agent/repository/custom-agent-repository-extension.ts
  • backend/src/entities/ai/user-ai-requests-v2.controller.ts
  • backend/src/entities/amplitude/amplitude.service.ts
  • backend/src/entities/company-info/company-info-helper.service.ts
  • backend/src/entities/company-info/use-cases/invite-user-in-company.use.case.ts
  • backend/src/entities/connection/connection.entity.ts
  • backend/src/entities/connection/utils/is-host-allowed.ts
  • backend/src/entities/connection/utils/validate-create-connection-data.ts
  • backend/src/entities/email/email-config/email-config.service.ts
  • backend/src/entities/email/email/email.service.ts
  • backend/src/entities/logging/winston-logger.ts
  • backend/src/entities/table-actions/table-action-rules-module/application/dto/create-action-rules-with-actions-and-events-body.dto.ts
  • backend/src/entities/table-actions/table-action-rules-module/use-cases/create-action-rule.use.case.ts
  • backend/src/entities/table-actions/table-action-rules-module/use-cases/update-action-rule-with-actions-and-events.use.case.ts
  • backend/src/entities/table-schema/utils/dynamodb-schema-op.ts
  • backend/src/entities/table/use-cases/find-tables-in-connection-v2.use.case.ts
  • backend/src/entities/table/use-cases/find-tables-in-connection.use.case.ts
  • backend/src/entities/user/utils/generate-gwt-token.ts
  • backend/src/entities/user/utils/get-cookie-domain-options.ts
  • backend/src/helpers/app/get-requeired-env-variable.ts
  • backend/src/helpers/app/is-saas.ts
  • backend/src/helpers/app/is-test.ts
  • backend/src/helpers/constants/constants.ts
  • backend/src/helpers/encryption/encryptor.ts
  • backend/src/helpers/get-process-variable.ts
  • backend/src/helpers/slack/slack-post-message.ts
  • backend/src/helpers/validators/is-action-url-host-allowed.ts
  • backend/src/helpers/validators/required-environment-variables.validator.ts
  • backend/src/helpers/validators/validation-helper.ts
  • backend/src/interceptors/timeout.interceptor.ts
  • backend/src/main.ts
  • backend/src/microservices/gateways/saas-gateway.ts/base-saas-gateway.service.ts
  • backend/src/microservices/gateways/saas-gateway.ts/utils/generate-saas-jwt.ts
  • backend/src/shared/config/app-config.ts
  • backend/src/shared/config/config.module.ts
  • backend/src/shared/config/config.service.ts
  • backend/src/shared/database/database.service.ts
  • backend/src/shared/services/turnstile.service.ts
💤 Files with no reviewable changes (3)
  • backend/src/helpers/validators/required-environment-variables.validator.ts
  • backend/src/helpers/app/get-requeired-env-variable.ts
  • backend/src/helpers/get-process-variable.ts


public async sendEmailToUser(letterContent: IMessage): Promise<SMTPTransport.SentMessageInfo | null> {
if (process.env.NODE_ENV === 'test') return;
if (isTest()) return;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Return null explicitly in test mode.

Line 38 currently returns undefined in a method contract that uses null for “no mail sent”, which can break callers that only branch on null.

Proposed fix
 	public async sendEmailToUser(letterContent: IMessage): Promise<SMTPTransport.SentMessageInfo | null> {
-		if (isTest()) return;
+		if (isTest()) return null;
 		const mailResult = await this.sendEmailWithTimeout(letterContent);
 		if (mailResult) {
 			return mailResult;
 		}
+		return null;
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (isTest()) return;
public async sendEmailToUser(letterContent: IMessage): Promise<SMTPTransport.SentMessageInfo | null> {
if (isTest()) return null;
const mailResult = await this.sendEmailWithTimeout(letterContent);
if (mailResult) {
return mailResult;
}
return null;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/entities/email/email/email.service.ts` at line 38, The test-mode
guard currently does "if (isTest()) return;" which returns undefined but callers
expect null for "no mail sent"; change that branch to "if (isTest()) return
null;" so the method in email.service.ts (the isTest() check inside the email
sending method) returns null explicitly in test mode to match the method
contract and avoid breaking null-only checks.

const slackBotToken = process.env.SLACK_BOT_ACCESS_TOKEN;
if (process.env.NODE_ENV === 'test' || !slackBotToken) {
const slackBotToken = appConfig.thirdParty.slackBotAccessToken;
if (appConfig.isTest || !slackBotToken) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Call isTest() in the guard to avoid always short-circuiting.

Line [8] checks appConfig.isTest directly. If isTest is a function (as used elsewhere), this branch always evaluates truthy and prevents Slack messages in all environments.

Proposed fix
-		if (appConfig.isTest || !slackBotToken) {
+		if (appConfig.isTest() || !slackBotToken) {
 			return;
 		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (appConfig.isTest || !slackBotToken) {
if (appConfig.isTest() || !slackBotToken) {
return;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/helpers/slack/slack-post-message.ts` at line 8, The guard
currently uses appConfig.isTest (a function reference) which always evaluates
truthy; change the condition to call the function (use appConfig.isTest()) so
the short-circuit only happens when tests are actually detected or when
slackBotToken is missing; update the conditional in slack-post-message.ts (the
if that references appConfig.isTest and slackBotToken) to use appConfig.isTest()
while preserving the existing || !slackBotToken logic.

port: readInt('EMAIL_SERVICE_PORT') ?? DEFAULT_EMAIL_PORT,
username: readString('EMAIL_SERVICE_USERNAME'),
password: readString('EMAIL_SERVICE_PASSWORD'),
nonSecure: readString('NON_SSL_EMAIL') === null,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Logic inversion for nonSecure configuration.

The current logic sets nonSecure: true when NON_SSL_EMAIL is not set. Typically, setting NON_SSL_EMAIL env var would indicate you want non-SSL email. The condition appears inverted.

🐛 Proposed fix
-			nonSecure: readString('NON_SSL_EMAIL') === null,
+			nonSecure: readString('NON_SSL_EMAIL') !== null,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/shared/config/app-config.ts` at line 167, The nonSecure flag is
inverted: currently nonSecure is true when readString('NON_SSL_EMAIL') === null;
change the logic so nonSecure reflects the presence of the env var by setting
nonSecure to a truthy check of the env value (e.g., nonSecure:
!!readString('NON_SSL_EMAIL') or nonSecure: readString('NON_SSL_EMAIL') !==
null) so that when NON_SSL_EMAIL is set, nonSecure becomes true; update the
property in the same config object where nonSecure is defined to use this
corrected condition.

const fullPath = this.isTest
? path.join(process.cwd(), ...pgLiteFolderPath.split('/'))
: path.join(__dirname, '..', '..', '..', pgLiteFolderPath);
console.info('\nPg Lite Folder Patch: ', pgLiteFolderPath, '\n');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Typo in log message.

"Patch" should be "Path".

✏️ Proposed fix
-			console.info('\nPg Lite Folder Patch: ', pgLiteFolderPath, '\n');
+			console.info('\nPg Lite Folder Path: ', pgLiteFolderPath, '\n');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
console.info('\nPg Lite Folder Patch: ', pgLiteFolderPath, '\n');
console.info('\nPg Lite Folder Path: ', pgLiteFolderPath, '\n');
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/shared/config/app-config.ts` at line 270, Fix the typo in the
console.info message: update the console.info call that logs pgLiteFolderPath
(the console.info('\nPg Lite Folder Patch: ', pgLiteFolderPath, '\n') statement)
to say "Path" instead of "Patch" so the log reads "Pg Lite Folder Path: " while
leaving pgLiteFolderPath and surrounding formatting unchanged.

Comment on lines +324 to +342
private parseTypeORMUrl(url: string): {
host: string;
port: number;
username: string;
password: string;
database: string;
ssl: any;
} {
const parsingResult = parse.parse(url);
const { host, port, user, password, database, ssl } = parsingResult;
return {
host,
port: parseInt(port, 10),
username: user,
password,
database,
ssl,
};
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Type safety issues in parseTypeORMUrl.

  1. ssl: any violates the "avoid any types" guideline.
  2. parse.parse() can return null for host, port, user, password, and database. If port is null, parseInt(port, 10) returns NaN, which doesn't match the declared return type.
🛡️ Proposed fix with proper null handling and types
 	private parseTypeORMUrl(url: string): {
 		host: string;
 		port: number;
 		username: string;
 		password: string;
 		database: string;
-		ssl: any;
+		ssl: boolean | Record<string, unknown> | undefined;
 	} {
 		const parsingResult = parse.parse(url);
 		const { host, port, user, password, database, ssl } = parsingResult;
+		if (!host || !port || !user || !password || !database) {
+			throw new Error('DATABASE_URL is missing required components (host, port, user, password, or database)');
+		}
 		return {
 			host,
 			port: parseInt(port, 10),
 			username: user,
 			password,
 			database,
-			ssl,
+			ssl: ssl as boolean | Record<string, unknown> | undefined,
 		};
 	}

As per coding guidelines: "Avoid any types - use specific types or generics instead"

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/shared/config/app-config.ts` around lines 324 - 342, The
parseTypeORMUrl function uses parse.parse() (from parse) which can return
nullable fields and currently types ssl as any; update the return type to be
strict (e.g., ssl: boolean | undefined or a specific SSL config type) and
defensively handle nullable parse results from parse.parse(url) by checking for
null/undefined for host, port, user, password, database and providing safe
defaults or throwing a clear error; ensure port is converted with Number(...) or
conditional parseInt only when port is a string and fall back to a default
number or undefined to match the return type; reference parseTypeORMUrl and
parse.parse in your changes.

@Artuomka Artuomka merged commit fcd29bd into main May 26, 2026
20 checks passed
@Artuomka Artuomka deleted the backend_config branch May 26, 2026 08:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants