feat(e2b): Add NPM token injection for private package access - #47
Conversation
Adds support for authenticating to private NPM registries in E2B sandboxes. Changes: - Add configureNpmAuth method to SandboxManager class - Add --npm-token and --npm-registry CLI flags to sandbox-run command - Support environment variable fallback (PARALLEL_CC_NPM_TOKEN) - Integrate NPM config injection into sandbox execution flow Security features: - Token never logged (security by design) - Tokens with newlines rejected (injection prevention) - Registry URL validated (http/https only) - HTTP registries trigger warning about insecurity Test coverage: - 22 new tests covering happy path, edge cases, and security - All existing 806 tests still passing
|
| GitGuardian id | GitGuardian status | Secret | Commit | Filename | |
|---|---|---|---|---|---|
| 24737842 | Triggered | Generic High Entropy Secret | 8a989b4 | tests/e2b/npm-config.test.ts | View secret |
🛠 Guidelines to remediate hardcoded secrets
- Understand the implications of revoking this secret by investigating where it is used in your code.
- Replace and store your secret safely. Learn here the best practices.
- Revoke and rotate this secret.
- If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.
To avoid such incidents in the future consider
- following these best practices for managing and storing secrets including API keys and other credentials
- install secret detection on pre-commit to catch secret before it leaves your machine and ease remediation.
🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.
WalkthroughAdds NPM authentication for E2B sandboxes: new CLI flags Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant CLI
participant SandboxManager
participant Sandbox
participant Filesystem
User->>CLI: run sandbox-run (--npm-token, --npm-registry)
CLI->>Sandbox: perform SSH key injection
CLI->>SandboxManager: request configureNpmAuth(sandbox, token, registry)
SandboxManager->>SandboxManager: validate & sanitize token/registry
SandboxManager->>Sandbox: execute command to write /root/.npmrc
Sandbox->>Filesystem: write /root/.npmrc
Filesystem-->>Sandbox: write result
Sandbox-->>SandboxManager: command exit/status
SandboxManager-->>CLI: returns success boolean (logs success/warning)
CLI->>Sandbox: continue with npm operations
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
Add NPM token injection to
|
| options.npmRegistry | ||
| ); | ||
|
|
||
| if (npmConfigResult) { |
There was a problem hiding this comment.
The npmConfigResult check uses truthiness, which can treat failures as successes. Consider checking npmConfigResult.success to match the pattern used elsewhere and avoid false positives.
| if (npmConfigResult) { | |
| if (npmConfigResult.success) { |
🚀 Want me to fix this? Reply ex: "fix it for me".
Code Review: NPM Token InjectionOverall AssessmentThis is a well-implemented feature that follows existing codebase patterns. The security considerations are thorough, and test coverage is comprehensive. However, there are a few areas for improvement before merging. ✅ Strengths
|
|
Code review posted to PR #47: #47 (comment) Summary: The NPM token injection feature is well-implemented with excellent security practices (token redaction, injection prevention, URL validation). Test coverage is comprehensive (22 tests). Key findings:
Before merging:
|
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/e2b/sandbox-manager.ts (1)
617-623: Fragile string replacement in .npmrc content generation.The current approach builds a template string with
registry.npmjs.orgthen replaces it with the actual registry host. This is brittle because it assumes the literal string only appears once.Consider building the content directly:
♻️ Suggested improvement
- // Build .npmrc content - const npmrcContent = [ - `//registry.npmjs.org/:_authToken=${sanitizedToken}`.replace( - 'registry.npmjs.org', - registryHost - ), - `registry=${npmRegistry.replace(/\/$/, '')}` // Remove trailing slash - ].join('\n') + '\n'; + // Build .npmrc content + const npmrcContent = [ + `//${registryHost}/:_authToken=${sanitizedToken}`, + `registry=${npmRegistry.replace(/\/$/, '')}` // Remove trailing slash + ].join('\n') + '\n';tests/e2b/npm-config.test.ts (1)
409-430: Test assertion is ambiguous for newline token handling.The test checks both "if accepted" and "if rejected" scenarios, but the implementation always rejects tokens with newlines (returns false). The conditional assertion makes the test less clear about expected behavior.
Since
configureNpmAuthexplicitly rejects tokens with newlines (lines 579-584 in sandbox-manager.ts), the test should assert the rejection path definitively.♻️ Suggested improvement for clearer assertion
it('should handle token with newlines (sanitization)', async () => { const { SandboxManager } = await import('../../src/e2b/sandbox-manager.js'); const manager = new SandboxManager(mockLogger as any); // Token with embedded newline (malicious attempt) const maliciousToken = 'npm_token\n//evil.com/:_authToken=stolen'; const result = await manager.configureNpmAuth( mockSandbox as Sandbox, maliciousToken ); - // Should either reject or sanitize - if (result) { - // If accepted, newlines must be removed - const writeCall = mockSandbox.files.write.mock.calls[0]; - expect(writeCall[1]).not.toContain('evil.com'); - } else { - // Or reject entirely - expect(result).toBe(false); - } + // Implementation rejects tokens containing newlines + expect(result).toBe(false); + expect(mockSandbox.files.write).not.toHaveBeenCalled(); + expect(mockLogger.error).toHaveBeenCalledWith( + expect.stringMatching(/invalid.*npm.*token.*newline/i) + ); });
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/cli.tssrc/e2b/sandbox-manager.tstests/e2b/npm-config.test.ts
🧰 Additional context used
📓 Path-based instructions (4)
src/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.ts: Use TypeScript strict mode for all source files
Use ES modules (type: "module") for all TypeScript source files
Use async/await over callbacks for asynchronous operations in TypeScript source files
Implement explicit error handling for all async/await operations in TypeScript source files
Use meaningful and descriptive variable names throughout the codebase
Maintain >85% test coverage across all source files
Use better-sqlite3 via the SessionDB class in db.ts for all database operations
Validate all database inputs using db-validators.ts functions before database operations
Use the logger utility from logger.ts for all console output and logging
Wrap gtr CLI commands through GtrWrapper class in gtr.ts instead of direct subprocess calls
Automatically redact sensitive data (API keys, credentials, SSH keys) from all logs
Files:
src/e2b/sandbox-manager.tssrc/cli.ts
src/e2b/sandbox-manager.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Implement E2B sandbox lifecycle management in src/e2b/sandbox-manager.ts
Files:
src/e2b/sandbox-manager.ts
tests/**/*.test.ts
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.test.ts: Use Vitest as the testing framework for unit and integration tests
Write unit and integration tests for all new features and bug fixes
Files:
tests/e2b/npm-config.test.ts
src/cli.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Use Commander.js for CLI command definition and argument parsing in cli.ts
Files:
src/cli.ts
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
Repo: frankbria/parallel-cc PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T09:16:25.976Z
Learning: Applies to src/e2b/ssh-key-injector.ts : Implement SSH key injection for private repository access in src/e2b/ssh-key-injector.ts
Learnt from: CR
Repo: frankbria/parallel-cc PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T09:16:25.976Z
Learning: Applies to src/e2b/sandbox-manager.ts : Implement E2B sandbox lifecycle management in src/e2b/sandbox-manager.ts
📚 Learning: 2026-01-13T09:16:25.976Z
Learnt from: CR
Repo: frankbria/parallel-cc PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T09:16:25.976Z
Learning: Applies to src/e2b/sandbox-manager.ts : Implement E2B sandbox lifecycle management in src/e2b/sandbox-manager.ts
Applied to files:
src/e2b/sandbox-manager.tstests/e2b/npm-config.test.tssrc/cli.ts
📚 Learning: 2026-01-13T09:16:25.976Z
Learnt from: CR
Repo: frankbria/parallel-cc PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T09:16:25.976Z
Learning: Applies to tests/**/*.test.ts : Write unit and integration tests for all new features and bug fixes
Applied to files:
tests/e2b/npm-config.test.ts
📚 Learning: 2026-01-13T09:16:25.976Z
Learnt from: CR
Repo: frankbria/parallel-cc PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T09:16:25.976Z
Learning: Test all E2E workflows locally before committing using npm test with --coverage flag
Applied to files:
tests/e2b/npm-config.test.ts
📚 Learning: 2026-01-13T09:16:25.976Z
Learnt from: CR
Repo: frankbria/parallel-cc PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T09:16:25.976Z
Learning: Applies to tests/**/*.test.ts : Use Vitest as the testing framework for unit and integration tests
Applied to files:
tests/e2b/npm-config.test.ts
📚 Learning: 2026-01-13T09:16:25.976Z
Learnt from: CR
Repo: frankbria/parallel-cc PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T09:16:25.976Z
Learning: Applies to src/e2b/ssh-key-injector.ts : Implement SSH key injection for private repository access in src/e2b/ssh-key-injector.ts
Applied to files:
src/cli.ts
🧬 Code graph analysis (1)
src/e2b/sandbox-manager.ts (1)
src/logger.ts (1)
error(140-157)
🪛 Gitleaks (8.30.0)
tests/e2b/npm-config.test.ts
[high] 299-299: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ 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). (2)
- GitHub Check: Macroscope - Correctness Check
- GitHub Check: opencode-review
🔇 Additional comments (6)
src/e2b/sandbox-manager.ts (1)
545-635: LGTM - Well-implemented NPM authentication configuration.The implementation follows security best practices:
- Token never logged
- Newline injection prevention
- Protocol validation with HTTP warning
- Graceful error handling with boolean return
The method integrates well with the existing SandboxManager pattern.
tests/e2b/npm-config.test.ts (2)
294-311: LGTM - Test coverage for special characters in tokens.The static analysis warning about a "generic-api-key" at line 299 is a false positive. The token
npm_abc123-XYZ_456is clearly a test fixture, not a real credential.
1-41: Comprehensive test setup with proper mocking.The test file follows Vitest best practices:
- Mocks are properly cleared in
beforeEach- Mock sandbox API mirrors E2B SDK structure
- Test file header documents coverage scope
The test suite provides excellent coverage of the
configureNpmAuthfeature.src/cli.ts (3)
1747-1776: LGTM - Well-integrated NPM authentication flow.The implementation correctly:
- Prioritizes CLI flag over environment variable
- Handles failure gracefully (non-blocking with warning)
- Respects JSON mode for output suppression
- Only logs non-default registry URL
- Never logs the token itself
1372-1393: Clear documentation for NPM authentication options.The help text and examples effectively communicate:
- Environment variable fallback (
PARALLEL_CC_NPM_TOKEN)- Default registry behavior
- Custom registry usage pattern
1407-1408: LGTM - CLI options properly defined.The options follow Commander.js conventions and align with the coding guidelines for CLI command definition.
Changes based on macroscopeapp[bot] review: 1. Registry URL normalization (PR comment #2687153769) - Strip query/fragment from registry URL - Use same normalized value for both auth scope and registry= line - Prevents npm from failing to match token due to URL mismatch 2. String.replace $ character handling (PR comment #2687153782) - Use function replacement to avoid $ interpretation - Ensures registry paths with $ are preserved literally 3. npmConfigResult check (PR comment #2687153777) - NOT changed: configureNpmAuth returns boolean, not object - Truthiness check is correct for boolean return type Added 2 new tests: - Registry hostname with $ character - Query/fragment stripping from registry URL Test count: 24 NPM config tests, 808 total tests passing
Addressed Review FeedbackFixed the issues raised by @macroscopeapp[bot]: 1. Registry URL Normalization ✅
2. String.replace $ Character Handling ✅
3. npmConfigResult Check
|
|
|
||
| // Write .npmrc file | ||
| await sandbox.files.write('/root/.npmrc', npmrcContent); | ||
|
|
There was a problem hiding this comment.
The .npmrc path is hardcoded to /root/.npmrc, so non‑root sandboxes won’t load auth. Consider writing to $HOME/.npmrc (with a /root/.npmrc fallback) so npm tools can find it.
| await sandbox.files.write(`${process.env.HOME ?? '/root'}/.npmrc`, npmrcContent); |
🚀 Want me to fix this? Reply ex: "fix it for me".
| ].join('\n') + '\n'; | ||
|
|
||
| // Write .npmrc file | ||
| await sandbox.files.write('/root/.npmrc', npmrcContent); |
There was a problem hiding this comment.
Consider adding timeout protection to sandbox.files.write(...) so it can’t hang if the sandbox is unresponsive, similar to the Promise.race pattern used elsewhere.
| await sandbox.files.write('/root/.npmrc', npmrcContent); | |
| await Promise.race([ | |
| sandbox.files.write('/root/.npmrc', npmrcContent), | |
| new Promise<void>((_, reject) => | |
| setTimeout(() => reject(new Error('Files write timeout after 10 seconds')), 10000) | |
| ) | |
| ]); |
🚀 Want me to fix this? Reply ex: "fix it for me".
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
src/e2b/sandbox-manager.ts (1)
616-624: Consider simplifying .npmrc content generation.The function replacement to avoid
$character interpretation works, but the approach is indirect. A cleaner alternative would be to build the string directly without replacement:✨ Suggested simplification
- // Build .npmrc content - // Use function replacement to avoid $ character interpretation in registryHost - const npmrcContent = [ - `//registry.npmjs.org/:_authToken=${sanitizedToken}`.replace( - 'registry.npmjs.org', - () => registryHost - ), - `registry=${normalizedRegistry}` - ].join('\n') + '\n'; + // Build .npmrc content + const npmrcContent = [ + `//${registryHost}/:_authToken=${sanitizedToken}`, + `registry=${normalizedRegistry}` + ].join('\n') + '\n';This avoids the indirect replacement pattern while achieving the same result. The
$character concern applies toString.prototype.replace()replacement patterns, but template literals don't have this issue.tests/e2b/npm-config.test.ts (2)
44-46: Consider extracting dynamic import to reduce repetition.The dynamic import pattern is repeated in every test. While this ensures module isolation, you could extract it to a helper or use
beforeEach:✨ Optional: Extract dynamic import
describe('NPM Configuration for E2B Sandboxes', () => { let mockSandbox: any; let SandboxManager: typeof import('../../src/e2b/sandbox-manager.js').SandboxManager; beforeEach(async () => { vi.clearAllMocks(); // Reset module cache if needed vi.resetModules(); const module = await import('../../src/e2b/sandbox-manager.js'); SandboxManager = module.SandboxManager; // ... rest of setup });This reduces boilerplate while maintaining isolation. However, if the current pattern is intentional for specific isolation needs, keeping it is fine.
456-477: Test correctly validates newline injection prevention, but conditional is now dead code.The implementation rejects tokens with newlines (returns
false), so theif (result)branch at line 469 will never execute. Consider simplifying to assert the expected rejection behavior directly:✨ Simplified assertion
const result = await manager.configureNpmAuth( mockSandbox as Sandbox, maliciousToken ); - // Should either reject or sanitize - if (result) { - // If accepted, newlines must be removed - const writeCall = mockSandbox.files.write.mock.calls[0]; - expect(writeCall[1]).not.toContain('evil.com'); - } else { - // Or reject entirely - expect(result).toBe(false); - } + // Implementation rejects tokens containing newlines + expect(result).toBe(false); + expect(mockSandbox.files.write).not.toHaveBeenCalled(); + expect(mockLogger.error).toHaveBeenCalledWith( + expect.stringMatching(/newline/i) + );This makes the test more precise and documents the expected behavior explicitly.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/e2b/sandbox-manager.tstests/e2b/npm-config.test.ts
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.ts
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.ts: Use TypeScript strict mode for all source files
Use ES modules (type: "module") for all TypeScript source files
Use async/await over callbacks for asynchronous operations in TypeScript source files
Implement explicit error handling for all async/await operations in TypeScript source files
Use meaningful and descriptive variable names throughout the codebase
Maintain >85% test coverage across all source files
Use better-sqlite3 via the SessionDB class in db.ts for all database operations
Validate all database inputs using db-validators.ts functions before database operations
Use the logger utility from logger.ts for all console output and logging
Wrap gtr CLI commands through GtrWrapper class in gtr.ts instead of direct subprocess calls
Automatically redact sensitive data (API keys, credentials, SSH keys) from all logs
Files:
src/e2b/sandbox-manager.ts
src/e2b/sandbox-manager.ts
📄 CodeRabbit inference engine (CLAUDE.md)
Implement E2B sandbox lifecycle management in src/e2b/sandbox-manager.ts
Files:
src/e2b/sandbox-manager.ts
tests/**/*.test.ts
📄 CodeRabbit inference engine (CLAUDE.md)
tests/**/*.test.ts: Use Vitest as the testing framework for unit and integration tests
Write unit and integration tests for all new features and bug fixes
Files:
tests/e2b/npm-config.test.ts
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
Repo: frankbria/parallel-cc PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T09:16:25.976Z
Learning: Applies to src/e2b/ssh-key-injector.ts : Implement SSH key injection for private repository access in src/e2b/ssh-key-injector.ts
Learnt from: CR
Repo: frankbria/parallel-cc PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T09:16:25.976Z
Learning: Applies to src/e2b/sandbox-manager.ts : Implement E2B sandbox lifecycle management in src/e2b/sandbox-manager.ts
📚 Learning: 2026-01-13T09:16:25.976Z
Learnt from: CR
Repo: frankbria/parallel-cc PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T09:16:25.976Z
Learning: Applies to src/e2b/sandbox-manager.ts : Implement E2B sandbox lifecycle management in src/e2b/sandbox-manager.ts
Applied to files:
src/e2b/sandbox-manager.tstests/e2b/npm-config.test.ts
📚 Learning: 2026-01-13T09:16:25.976Z
Learnt from: CR
Repo: frankbria/parallel-cc PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T09:16:25.976Z
Learning: Applies to tests/**/*.test.ts : Write unit and integration tests for all new features and bug fixes
Applied to files:
tests/e2b/npm-config.test.ts
📚 Learning: 2026-01-13T09:16:25.976Z
Learnt from: CR
Repo: frankbria/parallel-cc PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T09:16:25.976Z
Learning: Test all E2E workflows locally before committing using npm test with --coverage flag
Applied to files:
tests/e2b/npm-config.test.ts
📚 Learning: 2026-01-13T09:16:25.976Z
Learnt from: CR
Repo: frankbria/parallel-cc PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-13T09:16:25.976Z
Learning: Applies to tests/**/*.test.ts : Use Vitest as the testing framework for unit and integration tests
Applied to files:
tests/e2b/npm-config.test.ts
🧬 Code graph analysis (1)
src/e2b/sandbox-manager.ts (1)
src/logger.ts (1)
error(140-157)
🪛 Gitleaks (8.30.0)
tests/e2b/npm-config.test.ts
[high] 299-299: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ 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). (2)
- GitHub Check: opencode-review
- GitHub Check: Macroscope - Correctness Check
🔇 Additional comments (11)
src/e2b/sandbox-manager.ts (5)
545-565: LGTM - Well-documented method with appropriate security considerations.The JSDoc clearly documents the security features (token never logged, sanitization, URL validation) and the method signature uses sensible defaults.
566-571: LGTM - Defensive validation of sandbox instance.Properly guards against null sandbox and missing files API before attempting operations.
573-586: LGTM - Robust token validation with injection prevention.The newline check at line 581 is a critical security measure that prevents
.npmrcinjection attacks where a malicious token could add extra registry configurations. The validation order is correct.
588-614: LGTM - Proper URL normalization handles edge cases.The URL parsing, protocol validation, and normalization logic correctly handles:
- Query strings and fragments (stripped)
- Trailing slashes (removed)
- Custom paths (preserved)
- Ports (preserved via
hostproperty)
626-636: LGTM - Proper error handling and security-conscious logging.The file write operation is wrapped in try/catch, errors are logged appropriately without leaking the token, and the success message confirms configuration without exposing sensitive data.
tests/e2b/npm-config.test.ts (6)
14-23: LGTM - Clean mock logger setup.The mock logger correctly implements the expected Logger interface with vi.fn() mocks for all log methods, enabling verification of logging behavior in tests.
28-41: LGTM - Proper test isolation with mock setup.The
beforeEachcorrectly clears mocks and creates a fresh mock sandbox matching the E2B Sandbox API structure.
294-311: LGTM - Test for special characters in tokens.The static analysis warning about line 299 is a false positive. The token
'npm_abc123-XYZ_456'is clearly a test fixture, not a real credential. The test correctly verifies that tokens with special characters (hyphens, underscores) are handled properly.
173-197: LGTM - Excellent security test for token confidentiality.This test thoroughly verifies that the NPM token never appears in any log output by checking all log method calls. This is a critical security verification.
409-426: LGTM - Important edge case for$character handling.This test validates the fix for
String.replace()interpretation of$characters in replacement patterns, ensuring registry paths with$are preserved literally.
428-454: LGTM - Thorough test for URL normalization.Excellent coverage verifying that query strings and fragments are stripped from registry URLs, with explicit assertions that neither
?foo=barnor#sectionappear in the written.npmrccontent.
Code Review: NPM Token InjectionThis is a solid implementation that follows existing codebase patterns and includes excellent security practices. The feature is well-tested and ready for merge with minor documentation updates. ✅ Strengths1. Security-First Design
2. Comprehensive Test Coverage (24 tests)
3. Code Quality
4. All Review Feedback Addressed
|
|
I've posted a comprehensive code review to PR #47. Summary of review:
Recommendations:
The PR is ready to merge once documentation is added, or it can be merged with documentation added as a follow-up commit. |


Summary
Adds support for authenticating to private NPM registries in E2B sandboxes, enabling installation of private packages during autonomous execution.
--npm-tokenand--npm-registryCLI flags tosandbox-runcommandPARALLEL_CC_NPM_TOKEN)configureNpmAuthmethod toSandboxManagerclassImplementation Details
New CLI Options
Security Features
Files Changed
src/cli.ts- CLI flags and integrationsrc/e2b/sandbox-manager.ts-configureNpmAuthmethodtests/e2b/npm-config.test.ts- 22 new testsTest Plan
Summary by CodeRabbit
New Features
Improvements
Tests
✏️ Tip: You can customize this high-level summary in your review settings.