Skip to content

Conversation

@rmgpinto
Copy link
Collaborator

No description provided.

@coderabbitai
Copy link

coderabbitai bot commented Oct 14, 2025

Walkthrough

Derived a Redis TLS CA value from the environment variable REDIS_TLS_CERT_B64 (decoded and split into lines) and introduced a local caFromEnv used to set Redis TLS to { ca: caFromEnv } when present; otherwise tls stays undefined. Added a log line printing the Redis host/port and the TLS CA value. Separately, removed the lint job from the GitHub Actions workflow file .github/workflows/build.yml, leaving the other jobs intact.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 2 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title “WIP” is a vague placeholder that does not convey any information about the changes made in this pull request and thus fails to summarize the primary modifications. Please update the title to a concise sentence that reflects the main change, such as “Use TLS CA from environment in Redis configuration and remove lint job from CI workflow.”
Description Check ❓ Inconclusive No pull request description was provided by the author, leaving reviewers without any context for evaluating the changes and failing to describe the modifications made in this PR. Please add a brief description summarizing the key changes, such as the introduction of caFromEnv for Redis TLS configuration and the removal of the lint job from the GitHub Actions workflow.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch redis-tls-cert-b64

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

@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: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cfd3d45 and bc72ad2.

📒 Files selected for processing (1)
  • src/configuration/registrations.ts (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.ts: Never use direct string comparisons for ActivityPub IDs; use SHA256 hash-based lookups instead
Use Result helper functions (isError, getError, getValue) and avoid destructuring Result values directly
Awilix uses CLASSIC injection: constructor parameter names must match their registration names
Define routes using decorators rather than direct registration
Prefer immutable entities that emit domain events over mutable entities with dirty flags
Use structured error objects with context in Result types instead of string literals
Prefer class-based handlers with dependency injection over function factories

Files:

  • src/configuration/registrations.ts
🧠 Learnings (1)
📚 Learning: 2025-09-01T15:36:36.980Z
Learnt from: mike182uk
PR: TryGhost/ActivityPub#1251
File: docs/env-vars.md:67-74
Timestamp: 2025-09-01T15:36:36.980Z
Learning: MQ_PUBSUB_MAX_DELIVERY_ATTEMPTS is a required environment variable for production environments in the TryGhost/ActivityPub project, even though it's hardcoded in dev/pubsub/start.sh for development environments. The retry policy environment variables (MQ_PUBSUB_USE_RETRY_TOPIC, MQ_PUBSUB_RETRY_TOPIC_NAME, MQ_PUBSUB_MAX_DELIVERY_ATTEMPTS) should be documented as they are used in production configuration.

Applied to files:

  • src/configuration/registrations.ts
🧬 Code graph analysis (1)
src/configuration/registrations.ts (1)
src/pubsub.ts (1)
  • getFullTopic (18-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build / Build Docker Images (linux/amd64, amd64)

Comment on lines 136 to 143
: Buffer.from(
process.env
.REDIS_TLS_CERT_B64 ||
'',
'base64',
)
.toString('utf-8')
.split('\n'),
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Add error handling for base64 decoding.

The base64 decoding lacks validation. If REDIS_TLS_CERT_B64 contains invalid base64 or is empty, the connection will fail silently or with cryptic TLS errors at runtime.

Consider adding validation:

ca: process.env.REDIS_TLS_CERT ||
    (() => {
        const b64Cert = process.env.REDIS_TLS_CERT_B64;
        if (!b64Cert) {
            throw new Error('REDIS_TLS_CERT_B64 is empty');
        }
        try {
            const decoded = Buffer.from(b64Cert, 'base64').toString('utf-8');
            if (!decoded.includes('BEGIN CERTIFICATE')) {
                throw new Error('Decoded certificate does not appear to be valid PEM format');
            }
            return decoded;
        } catch (err) {
            throw new Error(`Failed to decode REDIS_TLS_CERT_B64: ${err.message}`);
        }
    })(),

This provides clear error messages during initialization rather than obscure TLS handshake failures later.

🤖 Prompt for AI Agents
In src/configuration/registrations.ts around lines 136 to 143, the code decodes
REDIS_TLS_CERT_B64 without validation; add explicit checks and error handling so
initialization fails with a clear message if the env var is missing, not valid
base64, or the decoded string doesn't look like a PEM certificate. Implement a
small validation flow: read REDIS_TLS_CERT_B64, throw if empty, attempt
Buffer.from(..., 'base64') inside a try/catch and throw a descriptive error on
failure, convert to utf-8 and verify it contains "BEGIN CERTIFICATE" (or other
PEM markers) and throw if not; use the validated decoded PEM as the ca value (or
fall back to REDIS_TLS_CERT when present).

Copy link

@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: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7830533 and d7ba077.

📒 Files selected for processing (1)
  • src/configuration/registrations.ts (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.ts: Never use direct string comparisons for ActivityPub IDs; use SHA256 hash-based lookups instead
Use Result helper functions (isError, getError, getValue) and avoid destructuring Result values directly
Awilix uses CLASSIC injection: constructor parameter names must match their registration names
Define routes using decorators rather than direct registration
Prefer immutable entities that emit domain events over mutable entities with dirty flags
Use structured error objects with context in Result types instead of string literals
Prefer class-based handlers with dependency injection over function factories

Files:

  • src/configuration/registrations.ts
🧠 Learnings (1)
📚 Learning: 2025-09-01T15:36:36.980Z
Learnt from: mike182uk
PR: TryGhost/ActivityPub#1251
File: docs/env-vars.md:67-74
Timestamp: 2025-09-01T15:36:36.980Z
Learning: MQ_PUBSUB_MAX_DELIVERY_ATTEMPTS is a required environment variable for production environments in the TryGhost/ActivityPub project, even though it's hardcoded in dev/pubsub/start.sh for development environments. The retry policy environment variables (MQ_PUBSUB_USE_RETRY_TOPIC, MQ_PUBSUB_RETRY_TOPIC_NAME, MQ_PUBSUB_MAX_DELIVERY_ATTEMPTS) should be documented as they are used in production configuration.

Applied to files:

  • src/configuration/registrations.ts
🧬 Code graph analysis (1)
src/configuration/registrations.ts (1)
src/pubsub.ts (1)
  • getFullTopic (18-20)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build / Build Docker Images (linux/amd64, amd64)
🔇 Additional comments (1)
src/configuration/registrations.ts (1)

140-140: LGTM!

The TLS configuration correctly uses caFromEnv when present and leaves tls undefined otherwise. This is the correct approach for conditional TLS.

Comment on lines +110 to +115
const caFromEnv = process.env.REDIS_TLS_CERT_B64
? Buffer.from(
process.env.REDIS_TLS_CERT_B64,
'base64',
).toString('utf8')
: undefined;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Regression: Missing REDIS_TLS_CERT fallback and error handling.

The current implementation has two issues:

  1. Regression: The previous review suggested considering REDIS_TLS_CERT as the primary option with REDIS_TLS_CERT_B64 as a fallback, but caFromEnv now only checks REDIS_TLS_CERT_B64.

  2. Missing validation: As flagged in a previous review, the base64 decoding lacks error handling. If REDIS_TLS_CERT_B64 contains invalid base64, the connection will fail with cryptic TLS errors at runtime instead of clear initialization errors.

Apply this diff to address both issues:

-                const caFromEnv = process.env.REDIS_TLS_CERT_B64
-                    ? Buffer.from(
-                        process.env.REDIS_TLS_CERT_B64,
-                        'base64',
-                    ).toString('utf8')
-                    : undefined;
+                const caFromEnv = (() => {
+                    if (process.env.REDIS_TLS_CERT) {
+                        return process.env.REDIS_TLS_CERT;
+                    }
+                    if (process.env.REDIS_TLS_CERT_B64) {
+                        try {
+                            const decoded = Buffer.from(
+                                process.env.REDIS_TLS_CERT_B64,
+                                'base64',
+                            ).toString('utf8');
+                            if (!decoded.includes('BEGIN CERTIFICATE')) {
+                                throw new Error(
+                                    'Decoded REDIS_TLS_CERT_B64 does not appear to be valid PEM format',
+                                );
+                            }
+                            return decoded;
+                        } catch (err) {
+                            throw new Error(
+                                `Failed to decode REDIS_TLS_CERT_B64: ${err instanceof Error ? err.message : String(err)}`,
+                            );
+                        }
+                    }
+                    return undefined;
+                })();
📝 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
const caFromEnv = process.env.REDIS_TLS_CERT_B64
? Buffer.from(
process.env.REDIS_TLS_CERT_B64,
'base64',
).toString('utf8')
: undefined;
// Derive Redis TLS CA from env, preferring raw PEM over base64
const caFromEnv = (() => {
if (process.env.REDIS_TLS_CERT) {
return process.env.REDIS_TLS_CERT;
}
if (process.env.REDIS_TLS_CERT_B64) {
try {
const decoded = Buffer.from(
process.env.REDIS_TLS_CERT_B64,
'base64',
).toString('utf8');
if (!decoded.includes('BEGIN CERTIFICATE')) {
throw new Error(
'Decoded REDIS_TLS_CERT_B64 does not appear to be valid PEM format',
);
}
return decoded;
} catch (err) {
throw new Error(
`Failed to decode REDIS_TLS_CERT_B64: ${err instanceof Error ? err.message : String(err)}`,
);
}
}
return undefined;
})();

Comment on lines +117 to +119
logging.info(
`Connecting to Redis at ${host}:${port} with TLS: ${caFromEnv}`,
);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Security: Avoid logging the full certificate.

The log statement prints the entire TLS certificate (caFromEnv), which is sensitive infrastructure data. Logging full certificates can expose sensitive information in log aggregation systems, monitoring tools, or when logs are shared for debugging.

Apply this diff to log only whether TLS is enabled:

                 logging.info(
-                    `Connecting to Redis at ${host}:${port} with TLS: ${caFromEnv}`,
+                    `Connecting to Redis at ${host}:${port} with TLS: ${caFromEnv ? 'enabled' : 'disabled'}`,
                 );
📝 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
logging.info(
`Connecting to Redis at ${host}:${port} with TLS: ${caFromEnv}`,
);
logging.info(
`Connecting to Redis at ${host}:${port} with TLS: ${caFromEnv ? 'enabled' : 'disabled'}`,
);
🤖 Prompt for AI Agents
In src/configuration/registrations.ts around lines 117 to 119, the log prints
the full TLS certificate via caFromEnv which is sensitive; remove the
certificate from logs and instead log only whether TLS is enabled. Replace the
caFromEnv interpolation with a boolean or string flag (e.g., tlsEnabled =
!!caFromEnv) and change the logging call to include host, port and tlsEnabled
(or "TLS enabled"/"TLS disabled"), ensuring the certificate value is never
written to logs.

Comment on lines 226 to +227
Number(process.env.MQ_PUBSUB_MAX_DELIVERY_ATTEMPTS) ||
Number.POSITIVE_INFINITY,
Number.POSITIVE_INFINITY,
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Validate required environment variable for production.

Using Number.POSITIVE_INFINITY as a fallback for MQ_PUBSUB_MAX_DELIVERY_ATTEMPTS could lead to infinite retries if the environment variable is not set in production. This is particularly concerning as it would prevent failed messages from ever being moved to a dead-letter topic.

Based on learnings

Consider adding validation that throws an error during initialization if this variable is missing in production:

const maxDeliveryAttempts = (() => {
    const value = Number(process.env.MQ_PUBSUB_MAX_DELIVERY_ATTEMPTS);
    if (!value && process.env.NODE_ENV === 'production') {
        throw new Error(
            'MQ_PUBSUB_MAX_DELIVERY_ATTEMPTS is required in production',
        );
    }
    return value || Number.POSITIVE_INFINITY;
})();

Then use maxDeliveryAttempts on line 227 instead of the inline expression.

🤖 Prompt for AI Agents
In src/configuration/registrations.ts around lines 226-227, the inline fallback
to Number.POSITIVE_INFINITY for
Number(process.env.MQ_PUBSUB_MAX_DELIVERY_ATTEMPTS) can cause infinite retries
in production; replace the inline expression with a validated const (e.g.,
compute maxDeliveryAttempts by parsing the env var, and if the parsed value is
falsy and NODE_ENV === 'production' throw an Error indicating
MQ_PUBSUB_MAX_DELIVERY_ATTEMPTS is required), then use that maxDeliveryAttempts
variable on line 227 instead of the current inline expression.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant