From 4cdbd20650971c879209a60619eee9504263003a Mon Sep 17 00:00:00 2001 From: Todd Martin Date: Wed, 17 Dec 2025 08:49:37 -0500 Subject: [PATCH 01/11] Update docs for bitwarden-core --- crates/bitwarden-core/README.md | 47 ++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/crates/bitwarden-core/README.md b/crates/bitwarden-core/README.md index 9b8b6e01c..7044b67f1 100644 --- a/crates/bitwarden-core/README.md +++ b/crates/bitwarden-core/README.md @@ -1,17 +1,40 @@ # Bitwarden Core -Contains core functionality used by the feature crates. For an introduction to the Bitwarden SDK and -the `bitwarden-core` create please refer to the -[SDK Architecture](https://contributing.bitwarden.com/architecture/sdk/) documentation. +Core infrastructure crate providing the base `Client` type - a container for runtime persistent data +and shared infrastructure that feature crates extend via extension traits. For an introduction to the +SDK architecture, see the [SDK Architecture](https://contributing.bitwarden.com/architecture/sdk/) +documentation. -
-Generally you should not find yourself needing to edit this crate! When possible, please use the feature crates instead. -
+> **Warning**: Do not add business logic or feature-specific functionality to this crate. Use feature crates instead. -## Features +## Architecture -- `internal` - Internal unstable APIs that should only be consumed by internal Bitwarden clients. -- `no-memory-hardening` - Disables `bitwarden-crypto` memory hardening. -- `secrets` - Secrets Manager specific functionality. -- `uniffi` - Mobile bindings. -- `wasm` - WebAssembly bindings. +### Client Structure + +The `Client` type serves as a **container for runtime persistent data**, which is intended to persist for the lifetime of the SDK instance. Think of this as "dependency injection" for the SDK instance. It should only contain: + +1. **User identity**: + - `UserId` - Ensures each client is immutably associated with one user +2. **Security state**: + - `KeyStore` - Secure in-memory key management +3. **Network state**: + - `ApiClient`/`ApiConfigurations` - HTTP client initialized once and reused + - `TokenRenew` trait - Implemented by `bitwarden-auth` crate for API client token renewal +4. **Storage state**: + - Database/state repository registration + +**Plain data** (tokens, flags, login info, profile data) should be accessed through `Repository` +implementations, not stored directly in `Client`. Historical fields exist due to incremental +migration - they will be moved to repositories over time. + +### Client vs InternalClient + +- `Client` is a lightweight wrapper around `Arc` +- `Arc` enables cheap cloning for FFI bindings (owned copies point to same underlying instance) +- `InternalClient` originally hid internal APIs from Secrets Manager, but this separation becomes less important as functionality moves to feature crates + +### Extension Pattern + +Feature crates extend `Client` via traits (e.g., `PasswordManagerClient` wraps `Client` and exposes `vault()`, `generators()` sub-clients). + +**Do not add feature functionality to `Client` itself.** \ No newline at end of file From 26be8dc1fd91eefc483c0b16da03c5234ede2f3b Mon Sep 17 00:00:00 2001 From: Todd Martin Date: Wed, 17 Dec 2025 09:04:25 -0500 Subject: [PATCH 02/11] Move docs from Contributing. --- crates/bitwarden-core/README.md | 39 ++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/crates/bitwarden-core/README.md b/crates/bitwarden-core/README.md index 7044b67f1..a92687004 100644 --- a/crates/bitwarden-core/README.md +++ b/crates/bitwarden-core/README.md @@ -5,7 +5,8 @@ and shared infrastructure that feature crates extend via extension traits. For a SDK architecture, see the [SDK Architecture](https://contributing.bitwarden.com/architecture/sdk/) documentation. -> **Warning**: Do not add business logic or feature-specific functionality to this crate. Use feature crates instead. +> [!WARNING] +> Do not add business logic or feature-specific functionality to this crate. Use feature crates instead. ## Architecture @@ -35,6 +36,38 @@ migration - they will be moved to repositories over time. ### Extension Pattern -Feature crates extend `Client` via traits (e.g., `PasswordManagerClient` wraps `Client` and exposes `vault()`, `generators()` sub-clients). +Feature crates extend `Client` via extension traits in feature crates. This allows the underlying implementation to be internal to the crate with only the public API exposed through the `Client` struct. Below is an example of a generator extension for the `Client` struct. -**Do not add feature functionality to `Client` itself.** \ No newline at end of file +> [!IMPORTANT] +> Do not add feature functionality to `Client` itself. + +```rust +/// Generator extension for the Client struct +#[cfg_attr(feature = "wasm", wasm_bindgen)] +pub struct GeneratorClient { + client: Client, +} + +#[cfg_attr(feature = "wasm", wasm_bindgen)] +impl GeneratorClient { + fn new(client: Client) -> Self { + Self { client } + } + + /// Generates a password based on the provided request. + pub fn password(&self, input: PasswordGeneratorRequest) -> Result { + password(input) + } +} + +/// Extension which exposes `generator` method on the `Client` struct. +pub trait GeneratorClientExt { + fn generator(&self) -> GeneratorClient; +} + +impl GeneratorClientExt for Client { + fn generator(&self) -> GeneratorClient { + GeneratorClient::new(self.clone()) + } +} +``` \ No newline at end of file From 5c3a82c0b46d96e686d9af7b4f2a792bcbd93eab Mon Sep 17 00:00:00 2001 From: Todd Martin Date: Wed, 17 Dec 2025 09:23:10 -0500 Subject: [PATCH 03/11] Updated header levels. --- crates/bitwarden-core/README.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/crates/bitwarden-core/README.md b/crates/bitwarden-core/README.md index a92687004..11851b075 100644 --- a/crates/bitwarden-core/README.md +++ b/crates/bitwarden-core/README.md @@ -8,9 +8,7 @@ documentation. > [!WARNING] > Do not add business logic or feature-specific functionality to this crate. Use feature crates instead. -## Architecture - -### Client Structure +## `Client` Structure The `Client` type serves as a **container for runtime persistent data**, which is intended to persist for the lifetime of the SDK instance. Think of this as "dependency injection" for the SDK instance. It should only contain: @@ -28,13 +26,13 @@ The `Client` type serves as a **container for runtime persistent data**, which i implementations, not stored directly in `Client`. Historical fields exist due to incremental migration - they will be moved to repositories over time. -### Client vs InternalClient +### `Client` vs `InternalClient` - `Client` is a lightweight wrapper around `Arc` - `Arc` enables cheap cloning for FFI bindings (owned copies point to same underlying instance) - `InternalClient` originally hid internal APIs from Secrets Manager, but this separation becomes less important as functionality moves to feature crates -### Extension Pattern +## Extension Pattern Feature crates extend `Client` via extension traits in feature crates. This allows the underlying implementation to be internal to the crate with only the public API exposed through the `Client` struct. Below is an example of a generator extension for the `Client` struct. From 0abd5ab609317f282883ed4b7253325474b5d02b Mon Sep 17 00:00:00 2001 From: Todd Martin Date: Wed, 17 Dec 2025 09:49:36 -0500 Subject: [PATCH 04/11] Make code compile. --- crates/bitwarden-core/README.md | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/crates/bitwarden-core/README.md b/crates/bitwarden-core/README.md index 11851b075..78aaa4265 100644 --- a/crates/bitwarden-core/README.md +++ b/crates/bitwarden-core/README.md @@ -39,8 +39,12 @@ Feature crates extend `Client` via extension traits in feature crates. This allo > [!IMPORTANT] > Do not add feature functionality to `Client` itself. -```rust -/// Generator extension for the Client struct +```rust,ignore +use bitwarden_core::Client; +#[cfg(feature = "wasm")] +use wasm_bindgen::prelude::*; + +/// Generator extension client that wraps the base Client #[cfg_attr(feature = "wasm", wasm_bindgen)] pub struct GeneratorClient { client: Client, @@ -52,20 +56,24 @@ impl GeneratorClient { Self { client } } - /// Generates a password based on the provided request. + /// Example method that uses the underlying Client pub fn password(&self, input: PasswordGeneratorRequest) -> Result { + // Implementation details... password(input) } } -/// Extension which exposes `generator` method on the `Client` struct. -pub trait GeneratorClientExt { - fn generator(&self) -> GeneratorClient; +/// Extension trait which exposes `generator()` method on the `Client` struct +pub trait GeneratorClientsExt { + fn generators(&self) -> GeneratorClient; } -impl GeneratorClientExt for Client { - fn generator(&self) -> GeneratorClient { +impl GeneratorClientsExt for Client { + fn generators(&self) -> GeneratorClient { GeneratorClient::new(self.clone()) } } + +// Usage: +// let password = client.generators().password(request)?; ``` \ No newline at end of file From 8405d0aa6f8c8dd335388ad7d886b3b14e16bccb Mon Sep 17 00:00:00 2001 From: Todd Martin Date: Wed, 17 Dec 2025 09:59:27 -0500 Subject: [PATCH 05/11] Updated token management docs. --- crates/bitwarden-core/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bitwarden-core/README.md b/crates/bitwarden-core/README.md index 78aaa4265..13548e880 100644 --- a/crates/bitwarden-core/README.md +++ b/crates/bitwarden-core/README.md @@ -18,7 +18,7 @@ The `Client` type serves as a **container for runtime persistent data**, which i - `KeyStore` - Secure in-memory key management 3. **Network state**: - `ApiClient`/`ApiConfigurations` - HTTP client initialized once and reused - - `TokenRenew` trait - Implemented by `bitwarden-auth` crate for API client token renewal + - `Tokens` enum - Includes `ClientManagedTokens` and `SdkManagedTokens` traits for access token management 4. **Storage state**: - Database/state repository registration From d78066883242d1fa1c7903904a5f57580a87ed26 Mon Sep 17 00:00:00 2001 From: Todd Martin Date: Wed, 17 Dec 2025 10:15:07 -0500 Subject: [PATCH 06/11] Corrections. --- crates/bitwarden-core/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bitwarden-core/README.md b/crates/bitwarden-core/README.md index 13548e880..a38aed8d2 100644 --- a/crates/bitwarden-core/README.md +++ b/crates/bitwarden-core/README.md @@ -18,7 +18,7 @@ The `Client` type serves as a **container for runtime persistent data**, which i - `KeyStore` - Secure in-memory key management 3. **Network state**: - `ApiClient`/`ApiConfigurations` - HTTP client initialized once and reused - - `Tokens` enum - Includes `ClientManagedTokens` and `SdkManagedTokens` traits for access token management + - `Tokens` enum - Includes `ClientManagedTokens` trait and `SdkManagedTokens` struct for access token management 4. **Storage state**: - Database/state repository registration @@ -34,7 +34,7 @@ migration - they will be moved to repositories over time. ## Extension Pattern -Feature crates extend `Client` via extension traits in feature crates. This allows the underlying implementation to be internal to the crate with only the public API exposed through the `Client` struct. Below is an example of a generator extension for the `Client` struct. +Feature crates extend `Client` via extension traits. This allows the underlying implementation to be internal to the crate with only the public API exposed through the `Client` struct. Below is an example of a generator extension for the `Client` struct. > [!IMPORTANT] > Do not add feature functionality to `Client` itself. From 5858013e17889800c1a33bc7d594fef64e5a3a4c Mon Sep 17 00:00:00 2001 From: Todd Martin Date: Wed, 17 Dec 2025 11:41:52 -0500 Subject: [PATCH 07/11] Linting. --- crates/bitwarden-core/README.md | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/crates/bitwarden-core/README.md b/crates/bitwarden-core/README.md index a38aed8d2..3ca9ecb84 100644 --- a/crates/bitwarden-core/README.md +++ b/crates/bitwarden-core/README.md @@ -1,16 +1,18 @@ # Bitwarden Core Core infrastructure crate providing the base `Client` type - a container for runtime persistent data -and shared infrastructure that feature crates extend via extension traits. For an introduction to the -SDK architecture, see the [SDK Architecture](https://contributing.bitwarden.com/architecture/sdk/) -documentation. +and shared infrastructure that feature crates extend via extension traits. For an introduction to +the SDK architecture, see the +[SDK Architecture](https://contributing.bitwarden.com/architecture/sdk/) documentation. -> [!WARNING] -> Do not add business logic or feature-specific functionality to this crate. Use feature crates instead. +> [!WARNING] Do not add business logic or feature-specific functionality to this crate. Use feature +> crates instead. ## `Client` Structure -The `Client` type serves as a **container for runtime persistent data**, which is intended to persist for the lifetime of the SDK instance. Think of this as "dependency injection" for the SDK instance. It should only contain: +The `Client` type serves as a **container for runtime persistent data**, which is intended to +persist for the lifetime of the SDK instance. Think of this as "dependency injection" for the SDK +instance. It should only contain: 1. **User identity**: - `UserId` - Ensures each client is immutably associated with one user @@ -18,7 +20,8 @@ The `Client` type serves as a **container for runtime persistent data**, which i - `KeyStore` - Secure in-memory key management 3. **Network state**: - `ApiClient`/`ApiConfigurations` - HTTP client initialized once and reused - - `Tokens` enum - Includes `ClientManagedTokens` trait and `SdkManagedTokens` struct for access token management + - `Tokens` enum - Includes `ClientManagedTokens` trait and `SdkManagedTokens` struct for access + token management 4. **Storage state**: - Database/state repository registration @@ -30,14 +33,16 @@ migration - they will be moved to repositories over time. - `Client` is a lightweight wrapper around `Arc` - `Arc` enables cheap cloning for FFI bindings (owned copies point to same underlying instance) -- `InternalClient` originally hid internal APIs from Secrets Manager, but this separation becomes less important as functionality moves to feature crates +- `InternalClient` originally hid internal APIs from Secrets Manager, but this separation becomes + less important as functionality moves to feature crates ## Extension Pattern -Feature crates extend `Client` via extension traits. This allows the underlying implementation to be internal to the crate with only the public API exposed through the `Client` struct. Below is an example of a generator extension for the `Client` struct. +Feature crates extend `Client` via extension traits. This allows the underlying implementation to be +internal to the crate with only the public API exposed through the `Client` struct. Below is an +example of a generator extension for the `Client` struct. -> [!IMPORTANT] -> Do not add feature functionality to `Client` itself. +> [!IMPORTANT] Do not add feature functionality to `Client` itself. ```rust,ignore use bitwarden_core::Client; @@ -76,4 +81,4 @@ impl GeneratorClientsExt for Client { // Usage: // let password = client.generators().password(request)?; -``` \ No newline at end of file +``` From ebc630b61e382e1607ef85a9477e12e7391bafb2 Mon Sep 17 00:00:00 2001 From: Todd Martin Date: Wed, 17 Dec 2025 21:09:04 -0500 Subject: [PATCH 08/11] Added API client docs. --- crates/bitwarden-core/README.md | 71 ++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/crates/bitwarden-core/README.md b/crates/bitwarden-core/README.md index 3ca9ecb84..8806b6552 100644 --- a/crates/bitwarden-core/README.md +++ b/crates/bitwarden-core/README.md @@ -8,7 +8,7 @@ the SDK architecture, see the > [!WARNING] Do not add business logic or feature-specific functionality to this crate. Use feature > crates instead. -## `Client` Structure +## `Client` structure The `Client` type serves as a **container for runtime persistent data**, which is intended to persist for the lifetime of the SDK instance. Think of this as "dependency injection" for the SDK @@ -36,7 +36,7 @@ migration - they will be moved to repositories over time. - `InternalClient` originally hid internal APIs from Secrets Manager, but this separation becomes less important as functionality moves to feature crates -## Extension Pattern +### Extension pattern Feature crates extend `Client` via extension traits. This allows the underlying implementation to be internal to the crate with only the public API exposed through the `Client` struct. Below is an @@ -82,3 +82,70 @@ impl GeneratorClientsExt for Client { // Usage: // let password = client.generators().password(request)?; ``` + +## API requests + +One of the responsibilities of the `Client` is managing and exposing the `ApiClient` instances for our API and Identity back-end services, which should be used to make HTTP requests. + +These `ApiClient`s should be accessed through the `ApiConfigurations` struct that is returned from the `get_api_configurations()` function. `get_api_configurations()` also refreshes the authentication token if required. + +```rust +// Example API call +let api_config: &ApiConfigurations = client.get_api_configurations().await; +let api_client: &bitwarden_api_api::apis::ApiClient = api_config.ApiClient; +let response = api_client.ciphers_api.get_all().await; +``` + +### Server API bindings + +To make the requests, we use auto-generated bindings whenever possible. We use `openapi-generator` to generate the Rust bindings from the server OpenAPI specifications. These bindings are regularly updated to ensure they stay in sync with the server. + +The bindings are exposed as multiple crates, one for each backend service: +- [`bitwarden-api-api`](../bitwarden-api-api/README.md): For the `Api` service that contains most of the server side functionality. +- [`bitwarden-api-identity`](../bitwarden-api-identity/README.md): For the `Identity` service that is used for authentication. + +When performing any API calls the goal is to use the generated bindings as much as possible. This ensures any changes to the server are accurately reflected in the SDK. The generated bindings are stateless, and always expects to be provided a Configuration instance. The SDK exposes these under the get_api_configurations function on the Client struct. + +You should not expose the request and response models of the auto-generated bindings and should instead define and use your own models. This ensures the server request / response models are decoupled from the SDK models and allows for easier changes in the future without breaking backwards compatibility. + +We recommend using either the `From` or `TryFrom` conversion traits depending on if the conversion requires error handling or not. Below are two examples of how this can be done: + +```rust +impl TryFrom for LoginUri { + type Error = Error; + + fn try_from(uri: bitwarden_api_api::models::CipherLoginUriModel) -> Result { + Ok(Self { + uri: EncString::try_from_optional(uri.uri)?, + r#match: uri.r#match.map(|m| m.into()), + uri_checksum: EncString::try_from_optional(uri.uri_checksum)?, + }) + } +} + +impl From for UriMatchType { + fn from(value: bitwarden_api_api::models::UriMatchType) -> Self { + match value { + bitwarden_api_api::models::UriMatchType::Domain => Self::Domain, + bitwarden_api_api::models::UriMatchType::Host => Self::Host, + bitwarden_api_api::models::UriMatchType::StartsWith => Self::StartsWith, + bitwarden_api_api::models::UriMatchType::Exact => Self::Exact, + bitwarden_api_api::models::UriMatchType::RegularExpression => Self::RegularExpression, + bitwarden_api_api::models::UriMatchType::Never => Self::Never, + } + } +} +``` + +### Updating bindings after a server API change + +When the API exposed by the server changes, new bindings will need to be generated to reflect this change for consumption in the SDK. This includes adding new fields to server request / response models, removing fields from models, or changing types of models. + +This can be done the following ways: +1. Run the `Update API Bindings` workflow in the `sdk-internal` repo. +2. Wait for an automatic binding update to run, which is scheduled every 2 weeks. + +Both of these will generate a PR that will require approval from any teams whose owned code is affected by the binding updates. + +> [!IMPORTANT] +> Bindings should **not** be updated manually as part of the changes to consume the new server API in the SDK. Doing so manually risks causing conflicts with the auto-generated bindings and causing more work in the future to address it. \ No newline at end of file From 7810317aa3b7cf41e8cb09f673631351c729ed23 Mon Sep 17 00:00:00 2001 From: Todd Martin Date: Thu, 18 Dec 2025 11:06:48 -0500 Subject: [PATCH 09/11] Make examples build. --- crates/bitwarden-core/README.md | 44 +++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/crates/bitwarden-core/README.md b/crates/bitwarden-core/README.md index 8806b6552..f66c0e175 100644 --- a/crates/bitwarden-core/README.md +++ b/crates/bitwarden-core/README.md @@ -90,10 +90,13 @@ One of the responsibilities of the `Client` is managing and exposing the `ApiCli These `ApiClient`s should be accessed through the `ApiConfigurations` struct that is returned from the `get_api_configurations()` function. `get_api_configurations()` also refreshes the authentication token if required. ```rust +# use bitwarden_core::Client; +# async fn example(client: &Client) -> Result<(), Box> { // Example API call -let api_config: &ApiConfigurations = client.get_api_configurations().await; -let api_client: &bitwarden_api_api::apis::ApiClient = api_config.ApiClient; -let response = api_client.ciphers_api.get_all().await; +let api_config = client.internal.get_api_configurations().await; +let response = api_config.api_client.ciphers_api.get_all().await?; +# Ok(()) +# } ``` ### Server API bindings @@ -111,14 +114,41 @@ You should not expose the request and response models of the auto-generated bind We recommend using either the `From` or `TryFrom` conversion traits depending on if the conversion requires error handling or not. Below are two examples of how this can be done: ```rust +# use bitwarden_crypto::EncString; +# use serde::{Serialize, Deserialize}; +# use serde_repr::{Serialize_repr, Deserialize_repr}; +# +# #[derive(Serialize, Deserialize, Debug, Clone)] +# struct LoginUri { +# pub uri: Option, +# pub r#match: Option, +# pub uri_checksum: Option, +# } +# +# #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, PartialEq)] +# #[repr(u8)] +# pub enum UriMatchType { +# Domain = 0, +# Host = 1, +# StartsWith = 2, +# Exact = 3, +# RegularExpression = 4, +# Never = 5, +# } +# +# #[derive(Debug)] +# struct VaultParseError; +# impl TryFrom for LoginUri { - type Error = Error; + type Error = VaultParseError; - fn try_from(uri: bitwarden_api_api::models::CipherLoginUriModel) -> Result { + fn try_from(uri: bitwarden_api_api::models::CipherLoginUriModel) -> Result { Ok(Self { - uri: EncString::try_from_optional(uri.uri)?, + uri: EncString::try_from_optional(uri.uri) + .map_err(|_| VaultParseError)?, r#match: uri.r#match.map(|m| m.into()), - uri_checksum: EncString::try_from_optional(uri.uri_checksum)?, + uri_checksum: EncString::try_from_optional(uri.uri_checksum) + .map_err(|_| VaultParseError)?, }) } } From 187cf8b3fd52c73052bf727bb8a2ee2c2be31202 Mon Sep 17 00:00:00 2001 From: Todd Martin Date: Thu, 18 Dec 2025 11:07:29 -0500 Subject: [PATCH 10/11] Linting. --- crates/bitwarden-core/README.md | 46 +++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/crates/bitwarden-core/README.md b/crates/bitwarden-core/README.md index f66c0e175..0b1092b4a 100644 --- a/crates/bitwarden-core/README.md +++ b/crates/bitwarden-core/README.md @@ -85,9 +85,12 @@ impl GeneratorClientsExt for Client { ## API requests -One of the responsibilities of the `Client` is managing and exposing the `ApiClient` instances for our API and Identity back-end services, which should be used to make HTTP requests. +One of the responsibilities of the `Client` is managing and exposing the `ApiClient` instances for +our API and Identity back-end services, which should be used to make HTTP requests. -These `ApiClient`s should be accessed through the `ApiConfigurations` struct that is returned from the `get_api_configurations()` function. `get_api_configurations()` also refreshes the authentication token if required. +These `ApiClient`s should be accessed through the `ApiConfigurations` struct that is returned from +the `get_api_configurations()` function. `get_api_configurations()` also refreshes the +authentication token if required. ```rust # use bitwarden_core::Client; @@ -97,21 +100,33 @@ let api_config = client.internal.get_api_configurations().await; let response = api_config.api_client.ciphers_api.get_all().await?; # Ok(()) # } -``` +``` ### Server API bindings -To make the requests, we use auto-generated bindings whenever possible. We use `openapi-generator` to generate the Rust bindings from the server OpenAPI specifications. These bindings are regularly updated to ensure they stay in sync with the server. +To make the requests, we use auto-generated bindings whenever possible. We use `openapi-generator` +to generate the Rust bindings from the server OpenAPI specifications. These bindings are regularly +updated to ensure they stay in sync with the server. The bindings are exposed as multiple crates, one for each backend service: -- [`bitwarden-api-api`](../bitwarden-api-api/README.md): For the `Api` service that contains most of the server side functionality. -- [`bitwarden-api-identity`](../bitwarden-api-identity/README.md): For the `Identity` service that is used for authentication. -When performing any API calls the goal is to use the generated bindings as much as possible. This ensures any changes to the server are accurately reflected in the SDK. The generated bindings are stateless, and always expects to be provided a Configuration instance. The SDK exposes these under the get_api_configurations function on the Client struct. +- [`bitwarden-api-api`](../bitwarden-api-api/README.md): For the `Api` service that contains most of + the server side functionality. +- [`bitwarden-api-identity`](../bitwarden-api-identity/README.md): For the `Identity` service that + is used for authentication. + +When performing any API calls the goal is to use the generated bindings as much as possible. This +ensures any changes to the server are accurately reflected in the SDK. The generated bindings are +stateless, and always expects to be provided a Configuration instance. The SDK exposes these under +the get_api_configurations function on the Client struct. -You should not expose the request and response models of the auto-generated bindings and should instead define and use your own models. This ensures the server request / response models are decoupled from the SDK models and allows for easier changes in the future without breaking backwards compatibility. +You should not expose the request and response models of the auto-generated bindings and should +instead define and use your own models. This ensures the server request / response models are +decoupled from the SDK models and allows for easier changes in the future without breaking backwards +compatibility. -We recommend using either the `From` or `TryFrom` conversion traits depending on if the conversion requires error handling or not. Below are two examples of how this can be done: +We recommend using either the `From` or `TryFrom` conversion traits depending on if the conversion +requires error handling or not. Below are two examples of how this can be done: ```rust # use bitwarden_crypto::EncString; @@ -169,13 +184,18 @@ impl From for UriMatchType { ### Updating bindings after a server API change -When the API exposed by the server changes, new bindings will need to be generated to reflect this change for consumption in the SDK. This includes adding new fields to server request / response models, removing fields from models, or changing types of models. +When the API exposed by the server changes, new bindings will need to be generated to reflect this +change for consumption in the SDK. This includes adding new fields to server request / response +models, removing fields from models, or changing types of models. This can be done the following ways: + 1. Run the `Update API Bindings` workflow in the `sdk-internal` repo. 2. Wait for an automatic binding update to run, which is scheduled every 2 weeks. -Both of these will generate a PR that will require approval from any teams whose owned code is affected by the binding updates. +Both of these will generate a PR that will require approval from any teams whose owned code is +affected by the binding updates. -> [!IMPORTANT] -> Bindings should **not** be updated manually as part of the changes to consume the new server API in the SDK. Doing so manually risks causing conflicts with the auto-generated bindings and causing more work in the future to address it. \ No newline at end of file +> [!IMPORTANT] Bindings should **not** be updated manually as part of the changes to consume the new +> server API in the SDK. Doing so manually risks causing conflicts with the auto-generated bindings +> and causing more work in the future to address it. From f167624c1480d03adf1ecad36835749fb37307da Mon Sep 17 00:00:00 2001 From: Todd Martin Date: Thu, 18 Dec 2025 12:03:59 -0500 Subject: [PATCH 11/11] Fixed compile error. --- crates/bitwarden-core/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bitwarden-core/README.md b/crates/bitwarden-core/README.md index 0b1092b4a..7f2f20a91 100644 --- a/crates/bitwarden-core/README.md +++ b/crates/bitwarden-core/README.md @@ -97,7 +97,7 @@ authentication token if required. # async fn example(client: &Client) -> Result<(), Box> { // Example API call let api_config = client.internal.get_api_configurations().await; -let response = api_config.api_client.ciphers_api.get_all().await?; +let response = api_config.api_client.ciphers_api().get_all().await?; # Ok(()) # } ```