Skip to content

Comments

⚡ Bolt: Cache redacted config for /api/config endpoint#97

Draft
Dexploarer wants to merge 1 commit intodevelopfrom
bolt-cache-config-endpoint-9905051820462622329
Draft

⚡ Bolt: Cache redacted config for /api/config endpoint#97
Dexploarer wants to merge 1 commit intodevelopfrom
bolt-cache-config-endpoint-9905051820462622329

Conversation

@Dexploarer
Copy link
Owner

💡 What: Caches the result of redactConfigSecrets(state.config) in ServerState.redactedConfig.
🎯 Why: GET /api/config involves a recursive deep copy and redaction of the configuration object. Caching this result avoids unnecessary CPU cycles, especially if the endpoint is polled frequently by the frontend.
📊 Impact: Reduces CPU usage for /api/config requests. The overhead is now O(1) for cached reads instead of O(N) where N is the config size.
🔬 Measurement: Verified that state.redactedConfig is populated after the first request and invalidated (set to null) after config mutation endpoints (like PUT /api/config or PUT /api/wallet/config) are called. Unit tests passed.


PR created automatically by Jules for task 9905051820462622329 started by @Dexploarer

Optimizes the `GET /api/config` endpoint by caching the redacted configuration in memory. This reduces CPU usage for frequent polling by avoiding recursive object traversal and cloning on every request.

The cache is automatically invalidated whenever the configuration is updated via API endpoints (e.g., onboarding, wallet config, plugin toggle).
@google-labs-jules
Copy link

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@github-actions github-actions bot added the tests label Feb 19, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 19, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch bolt-cache-config-endpoint-9905051820462622329

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.

@gemini-code-assist
Copy link

Summary of Changes

Hello @Dexploarer, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant performance improvement for the /api/config endpoint by caching the redacted configuration. Previously, each request to this endpoint involved a computationally intensive deep copy and redaction process. By storing the result in a dedicated cache, subsequent requests can retrieve the configuration in constant time, drastically reducing CPU cycles. The cache is diligently invalidated across all relevant configuration mutation endpoints to ensure data consistency.

Highlights

  • Performance Optimization: Implemented caching for the /api/config endpoint to reduce CPU usage by avoiding repeated deep copies and redactions of the configuration object.
  • Cache Invalidation: Ensured the cached redacted configuration is invalidated (set to null) whenever the application's configuration is modified through various API endpoints.
  • State Management: Introduced a redactedConfig property to the ServerState interface to store the cached configuration.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/api/cloud-routes.test.ts
    • Updated formatting for function calls and expect assertions in cloud route tests.
  • src/api/database.test.ts
    • Refactored formatting within mock pg pool and dns.lookup implementations.
    • Adjusted formatting for expect assertions in database security tests.
  • src/api/server.ts
    • Added redactedConfig property to the ServerState interface.
    • Initialized redactedConfig to null in the startApiServer function.
    • Implemented caching logic for the /api/config endpoint using state.redactedConfig.
    • Added cache invalidation (state.redactedConfig = null;) to various config mutation handlers, including those for Anthropic API key, onboarding, reset, config updates, wallet config, and skills API key.
  • test/api-security-headers.e2e.test.ts
    • Adjusted formatting for expect assertions in security header end-to-end tests.
Activity
  • PR created automatically by Jules for task 9905051820462622329, started by @Dexploarer.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Comment on lines 75 to 96
json: async () => ({}),
});

const handled = await handleCloudRoute(req, res, "/api/cloud/login", "POST", state);
const handled = await handleCloudRoute(
req,
res,
"/api/cloud/login",
"POST",
state,
);

expect(handled).toBe(true);
expect(fetchMock).toHaveBeenCalledWith(
expect.stringContaining("/api/auth/cli-session"),
expect.objectContaining({ method: "POST" })
expect.objectContaining({ method: "POST" }),
);
expect(res.end).toHaveBeenCalledWith(
expect.stringContaining('"sessionId"'),
);
expect(res.end).toHaveBeenCalledWith(expect.stringContaining('"sessionId"'));
});

it("GET /api/cloud/login/status handles authenticated state", async () => {

Choose a reason for hiding this comment

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

The tests for POST /api/cloud/login and GET /api/cloud/login/status only cover the successful (happy path) scenarios. There are no tests for error cases, such as when the fetch call fails (e.g., network error, non-OK response, or invalid JSON). This could result in unhandled exceptions or incorrect error handling in the route handler.

Recommendation:
Add tests that simulate fetch failures and verify that the handler responds appropriately (e.g., with an error message or status code), ensuring robust error handling.

Comment on lines 107 to 119
}),
});

const handled = await handleCloudRoute(req, res, "/api/cloud/login/status", "GET", state);
const handled = await handleCloudRoute(
req,
res,
"/api/cloud/login/status",
"GET",
state,
);

expect(handled).toBe(true);
// Should save config

Choose a reason for hiding this comment

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

The test for GET /api/cloud/login/status mutates process.env by setting ELIZAOS_CLOUD_API_KEY and ELIZAOS_CLOUD_ENABLED. This mutation is not reverted after the test, which can lead to side effects and test pollution, especially if other tests depend on these environment variables.

Recommendation:
Store the original values of the environment variables before the test and restore them in an afterEach block to ensure test isolation and prevent side effects.

Comment on lines 148 to 164
it("POST /api/database/query rejects mutation keywords in read-only mode", async () => {
const { req, res } = createMocks("POST", "/api/database/query", {
sql: "DELETE FROM users",
});

await handleDatabaseRoute(req, res, { adapter: {} } as any, "/api/database/query");
await handleDatabaseRoute(
req,
res,
{ adapter: {} } as any,
"/api/database/query",
);

expect(res.statusCode).toBe(400);
expect(res.end).toHaveBeenCalledWith(expect.stringContaining("mutation keyword"));
expect(res.end).toHaveBeenCalledWith(
expect.stringContaining("mutation keyword"),
);
});

Choose a reason for hiding this comment

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

Incomplete mutation keyword coverage in read-only mode test

The test for mutation keywords in read-only mode only checks for 'DELETE'. If the implementation blocks other mutation keywords (e.g., 'UPDATE', 'INSERT'), these are not covered. To ensure comprehensive coverage, parameterize the test to check all mutation keywords:

const mutationKeywords = ["DELETE", "UPDATE", "INSERT", "DROP", "ALTER"];
mutationKeywords.forEach(keyword => {
  it(`POST /api/database/query rejects ${keyword} in read-only mode`, async () => {
    const { req, res } = createMocks("POST", "/api/database/query", { sql: `${keyword} FROM users` });
    await handleDatabaseRoute(req, res, { adapter: {} } as any, "/api/database/query");
    expect(res.statusCode).toBe(400);
    expect(res.end).toHaveBeenCalledWith(expect.stringContaining("mutation keyword"));
  });
});

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a caching mechanism for the /api/config endpoint to improve performance, which is a great initiative. The implementation correctly uses the cache for GET requests and invalidates it across numerous endpoints that modify the configuration.

However, I've identified a critical issue where the cache is not invalidated after a PUT /api/config request, which will lead to serving stale data. I've also suggested a refactoring to centralize the cache invalidation logic, which would improve code maintainability and prevent similar bugs in the future.

Apart from these points, the changes look good and the test file modifications are just formatting updates.

Comment on lines +4660 to +4663
if (!state.redactedConfig) {
state.redactedConfig = redactConfigSecrets(state.config);
}
json(res, state.redactedConfig);

Choose a reason for hiding this comment

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

critical

This caching is a good optimization. However, I've found a case where the cache is not invalidated. The PUT /api/config endpoint modifies the configuration but does not clear state.redactedConfig. This will cause GET /api/config to return stale data after a PUT request.

To fix this, you should invalidate the cache in the PUT /api/config handler, similar to how it's done in other config-mutating endpoints.

Comment on lines 1775 to +1776
saveMilaidyConfig(state.config);
state.redactedConfig = null;

Choose a reason for hiding this comment

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

medium

I see this pattern of saveMilaidyConfig(state.config); followed by state.redactedConfig = null; repeated in many places. To improve maintainability and avoid forgetting to invalidate the cache in the future (like in the PUT /api/config endpoint), I suggest creating a helper function.

For example:

function saveConfigAndInvalidateCache(state: ServerState): void {
  saveMilaidyConfig(state.config);
  state.redactedConfig = null;
}

Then you can replace the repeated two lines with a single call to this new function. This will make the code cleaner and more robust.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant