Skip to content

Conversation

@coroiu
Copy link
Contributor

@coroiu coroiu commented Nov 6, 2025

🎟️ Tracking

📔 Objective

Add JS-compatible session repository implementation. I also added the ability to switch for situations where state providers might not make sense, for example if they will use insecure IPC to save the data, defeating the whole point of a secure session.

⏰ Reminders before review

  • Contributor guidelines followed
  • All formatters and local linters executed and passed
  • Written new unit and / or integration tests where applicable
  • Protected functional changes with optionality (feature flags)
  • Used internationalization (i18n) for all UI strings
  • CI builds passed
  • Communicated to DevOps any deployment requirements
  • Updated any necessary documentation (Confluence, contributing docs) or informed the documentation
    team

🦮 Reviewer guidelines

  • 👍 (:+1:) or similar for great changes
  • 📝 (:memo:) or ℹ️ (:information_source:) for notes or general info
  • ❓ (:question:) for questions
  • 🤔 (:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed
    issue and could potentially benefit from discussion
  • 🎨 (:art:) for suggestions / improvements
  • ❌ (:x:) or ⚠️ (:warning:) for more significant problems or concerns needing attention
  • 🌱 (:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt
  • ⛏ (:pick:) for minor or nitpick changes

@github-actions
Copy link
Contributor

github-actions bot commented Nov 6, 2025

Logo
Checkmarx One – Scan Summary & Detailsb878ec54-8901-4856-8fa2-1e154d3cc286

Great job! No new security vulnerabilities introduced in this pull request

Copy link

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 introduces JavaScript-managed session repositories for the IPC client in WASM environments. The changes enable WebAssembly clients to manage IPC sessions using their own state providers instead of relying solely on in-memory storage within the SDK.

Key changes:

  • Added JsSessionRepository for JavaScript-backed session management
  • Created GenericSessionRepository enum to support both in-memory and JavaScript-backed session repositories
  • Refactored JsIpcClient constructors to support both repository types

Reviewed Changes

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

File Description
crates/bitwarden-ipc/src/wasm/mod.rs Added module imports and re-exports for new session repository types
crates/bitwarden-ipc/src/wasm/js_session_repository.rs Implements JavaScript-backed session repository with thread-safe wrapper
crates/bitwarden-ipc/src/wasm/ipc_client.rs Refactored to use GenericSessionRepository with two factory methods for different session repository types
crates/bitwarden-ipc/src/wasm/generic_session_repository.rs Enum wrapper providing unified interface for different session repository implementations

Comment on lines +11 to +14
pub enum GenericSessionRepository {
InMemory(Arc<InMemorySessionRepository<Session>>),
JsSessionRepository(Arc<JsSessionRepository>),
}
Copy link

Copilot AI Nov 6, 2025

Choose a reason for hiding this comment

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

The GenericSessionRepository enum is missing a Clone implementation. This is required because IpcClient clones itself (via Arc::clone) in the start method (line 172 of ipc_client.rs) and handle_rpc_request method (line 338 of ipc_client.rs), which requires all fields to be cloneable. Since both variants contain Arc, add: #[derive(Clone)] above the enum definition.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@copilot But I don't need JsIpcClient to be cloneable, plus, start takes self: &Arc<Self> which clones the Arc not the actual IpcClient

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lol, created a whole new PR just to acknowledge it was wrong

@codecov
Copy link

codecov bot commented Nov 6, 2025

Codecov Report

❌ Patch coverage is 0% with 100 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.63%. Comparing base (ac71502) to head (3957ea5).
⚠️ Report is 12 commits behind head on main.

Files with missing lines Patch % Lines
...twarden-ipc/src/wasm/generic_session_repository.rs 0.00% 41 Missing ⚠️
...es/bitwarden-ipc/src/wasm/js_session_repository.rs 0.00% 39 Missing ⚠️
crates/bitwarden-ipc/src/wasm/ipc_client.rs 0.00% 20 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #547      +/-   ##
==========================================
+ Coverage   78.36%   79.63%   +1.27%     
==========================================
  Files         291      300       +9     
  Lines       29343    32247    +2904     
==========================================
+ Hits        22994    25680    +2686     
- Misses       6349     6567     +218     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link

Copilot AI commented Nov 6, 2025

@coroiu I've opened a new pull request, #548, to work on those changes. Once the pull request is ready, I'll request review from you.

@coroiu coroiu marked this pull request as ready for review November 6, 2025 09:56
@coroiu coroiu requested a review from a team as a code owner November 6, 2025 09:56
@coroiu coroiu requested a review from dani-garcia November 6, 2025 09:56
@claude
Copy link

claude bot commented Nov 6, 2025

Claude finished @coroiu's task —— View job


Code Review Complete

This PR implements JavaScript-managed session repositories for IPC clients in WASM environments, allowing clients to manage sessions using their own state providers. The implementation is well-structured with proper thread safety and clear separation of concerns.

Findings

Finding 1 ⚠️: Error conversion loses type safety and context in js_session_repository.rs:68

Finding 2 ♻️: Hardcoded Session type creates technical debt in generic_session_repository.rs:16

Finding 3 💭: Missing documentation for error handling contract in JavaScript interface at js_session_repository.rs:10

Finding 4 🎨: Constructor naming could better reflect the security distinction at ipc_client.rs:56

Good Practices Observed

  • Proper use of ThreadBoundRunner for WASM thread safety
  • Clear separation between in-memory and JS-backed implementations
  • Comprehensive TypeScript type definitions for JavaScript interface

Action Items

  1. Review error handling strategy for JS boundary crossings (Finding 1)
  2. Address the TODO comment about session type when implementing encryption (Finding 2)
  3. Consider documenting error handling expectations for JS implementers (Finding 3)
  4. Consider renaming constructors to emphasize security implications (Finding 4)

@coroiu
Copy link
Contributor Author

coroiu commented Nov 6, 2025

Claude review responses:

  1. Fixed
  2. Fixed
  3. I don't know how the struct is gonna lock and I don't mind breaking changes (which won't actually break because TS just sees any)
  4. That is fine, I'm writing facades/integrations. The effort to test that wasm_bindgen_serde does what it is supposed to far outweighs the benefits.
  5. We don't need to catch these errors and implementing errors that can propagate through JS -> WASM -> JS across multiple threads will just be a waste of time. If we need to catch them then we can implement that later.
  6. Breaking change is fine, I have a PR lined up.
  7. Intentional. The JS side doesn't need to know how the data looks. Adding a generic parameter will do nothing because the structure is not actually defined by JS.
  8. Fixed
  9. This is required because JsSessionRepository doesn't define the generic parameter, leaving the compiler confused and unable to automatically infer the types.
  10. Meh, we don't really have logging as a requirement.

EDIT: Apparently claude just modifies its existing comment so these numbers are no longer valid 🤷

@coroiu
Copy link
Contributor Author

coroiu commented Nov 6, 2025

Wow Claude, thank you for giving me a suggestion and then raising your own suggestion as a critical issue 👍 👍 👍 👍

async fn get(&self, endpoint: Endpoint) -> Result<Option<Session>, Self::GetError> {
self.0
.run_in_thread(move |repo| async move {
let js_value = repo.get(endpoint).await.map_err(|e| format!("{e:?}"))?;
Copy link

Choose a reason for hiding this comment

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

Finding 1 ⚠️: Error conversion loses type safety and context

Converting errors to strings using format!("{e:?}") loses structured error information and makes it difficult for callers to handle specific error cases programmatically. The same pattern appears on lines 74, 84, 87, and 96.

Context

Since you mentioned in PR comments that "We don't need to catch these errors" and implementing proper error propagation across JS/WASM boundaries is costly, this is acceptable for the current use case. However, this creates technical debt if error handling requirements change later.

Consider documenting this decision in a comment explaining that errors are intentionally simplified because they're not expected to be handled programmatically by consuming applications.

wasm::JsSessionRepository,
};

// TODO: Change session type when implementing encryption
Copy link

Choose a reason for hiding this comment

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

Finding 2 ♻️: Hardcoded Session type creates technical debt

The hardcoded type Session = () means this enum cannot support typed sessions until refactored. When encryption is implemented, this will require either:

  1. Breaking API changes to add a generic parameter
  2. Runtime type erasure with increased complexity

The TODO acknowledges this, but consider whether the wasm-bindgen limitation could be worked around by:

  • Using a trait object approach
  • Implementing separate constructors for different session types
  • Deferring type parameter resolution to a later point in the API


#[wasm_bindgen(typescript_custom_section)]
const TS_CUSTOM_TYPES: &'static str = r#"
export interface IpcSessionRepository {
Copy link

Choose a reason for hiding this comment

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

Finding 3 💭: Missing documentation for error handling contract

The TypeScript interface doesn't document what happens when these Promise methods throw errors. JavaScript consumers need to know:

  • What types of errors to expect
  • Whether they should implement error handling
  • What the consequences of errors are for session state

Consider adding JSDoc comments to the interface explaining the error contract, especially since errors are converted to strings and not propagated meaningfully.

/// Create a new `IpcClient` instance with an in-memory session repository for saving
/// sessions within the SDK.
#[wasm_bindgen(js_name = newWithSdkInMemorySessions)]
pub fn new_with_sdk_in_memory_sessions(
Copy link

Choose a reason for hiding this comment

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

Finding 4 🎨: Constructor naming could better reflect the security distinction

The PR description mentions that in-memory sessions are preferred "when state providers might not make sense, for example if they will use insecure IPC to save the data, defeating the whole point of a secure session."

Consider renaming to emphasize this security aspect:

  • newWithSecureInMemorySessions instead of newWithSdkInMemorySessions
  • Or add documentation explaining the security implications of each choice

This would help JavaScript consumers make informed security decisions rather than viewing this as simply an implementation detail preference.

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.

3 participants