Skip to content

Conversation

gbubemismith
Copy link
Contributor

🎟️ Tracking

https://bitwarden.atlassian.net/browse/PM-25818

📔 Objective

⏰ 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

@gbubemismith gbubemismith requested review from a team as code owners September 15, 2025 14:34
Copy link
Contributor

github-actions bot commented Sep 15, 2025

Logo
Checkmarx One – Scan Summary & Details24e3be60-0d10-4d8f-b0ca-40bdfcb00023

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

Copy link
Contributor

@nick-livefront nick-livefront left a comment

Choose a reason for hiding this comment

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

Just a handful of questions from me. I'm following this and the implementation but I would say that my rust experience is a little lack luster on if there are improvements to be made on that thread. I will hold off on approving to hopefully solicit some more impactful feedback, but I can if I'm the gateway between moving this forward.

Comment on lines 844 to 845
organization_use_totp: cipher.organization_use_totp.unwrap_or(true),
edit: cipher.edit.unwrap_or(true),
Copy link
Contributor

Choose a reason for hiding this comment

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

❓ Probably an edge case, the current CipherView defaults these values to false rather than true. Should this logic follow suit or is the deviation intentional?

list_ciphers(key_store, repository.as_ref()).await
}

/// Get [Cipher] by ID from state and decrypt it to a [CipherView].
Copy link
Contributor

Choose a reason for hiding this comment

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

I did not know you could link to other entities in a comment with [...], TIL!

@gbubemismith gbubemismith marked this pull request as draft September 15, 2025 19:47
dani-garcia and others added 9 commits September 15, 2025 16:45
## 🎟️ Tracking

<!-- Paste the link to the Jira or GitHub issue or otherwise describe /
point to where this change is coming from. -->

## 📔 Objective

These crates had some missing features, which caused compilation errors
when trying to run the tests from VSCode. The reason that CI kept
building was that rust unifies all the workspace features, so as long as
one crate has them enabled it's fine. On the other hand, when running a
test from VSCode, it will only have that crates features in mind.

Note that the uniffi feature of core requires internal because of these
two types:
https://github.com/bitwarden/sdk-internal/blob/main/crates/bitwarden-core/src/uniffi_support.rs#L30-L42

## ⏰ 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

<!-- Suggested interactions but feel free to use (or not) as you desire!
-->

- 👍 (`:+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
Scaffolds a new workflow for updating API bindings.
Updated SDK to use an `archivedDate` in the ciphers.
This PR contains the following updates:

| Package | Change | Age | Confidence |
|---|---|---|---|
|
[@openapitools/openapi-generator-cli](https://redirect.github.com/OpenAPITools/openapi-generator-cli)
| [`2.20.2` ->
`2.23.1`](https://renovatebot.com/diffs/npm/@openapitools%2fopenapi-generator-cli/2.20.2/2.23.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@openapitools%2fopenapi-generator-cli/2.23.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@openapitools%2fopenapi-generator-cli/2.20.2/2.23.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>OpenAPITools/openapi-generator-cli
(@&#8203;openapitools/openapi-generator-cli)</summary>

###
[`v2.23.1`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.23.1)

[Compare
Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.23.0...v2.23.1)

##### Bug Fixes

- **deps:** update dependency concurrently to v9.2.1
([#&#8203;978](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/978))
([4847fe0](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/4847fe0117995db49017c5943e18a6771a88929a))

###
[`v2.23.0`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.23.0)

[Compare
Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.22.0...v2.23.0)

##### Features

- **release:** v7.15.0 release
([#&#8203;973](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/973))
([24443a5](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/24443a5ff0b1d201b1ecef2299d82b96ffefd10c))

###
[`v2.22.0`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.22.0)

[Compare
Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.21.5...v2.22.0)

##### Features

- **release:** trigger a release
([#&#8203;963](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/963))
([7ce2ed9](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/7ce2ed95eb0bc3fb03bbe7c6f7bdcecd0091794b))

###
[`v2.21.5`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.21.5)

[Compare
Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.21.4...v2.21.5)

##### Bug Fixes

- **deps:** update dependency fs-extra to v11.3.1
([#&#8203;962](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/962))
([e0ce66f](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/e0ce66f36f3dc54539425ff58ddb0d8fd730dc98))

###
[`v2.21.4`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.21.4)

[Compare
Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.21.3...v2.21.4)

##### Bug Fixes

- **deps:** update dependency axios to v1.11.0 \[security]
([#&#8203;956](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/956))
([e517c31](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/e517c31ce8697225329e630c03697c147952b660))

###
[`v2.21.3`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.21.3)

[Compare
Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.21.2...v2.21.3)

##### Bug Fixes

- **deps:** update nest monorepo to v11.1.5
([#&#8203;950](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/950))
([28c5f0d](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/28c5f0d8b937bee531a16efb4d6c51017d0ac16c))

###
[`v2.21.2`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.21.2)

[Compare
Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.21.1...v2.21.2)

##### Bug Fixes

- **deps:** update dependency
[@&#8203;nestjs/axios](https://redirect.github.com/nestjs/axios) to
v4.0.1
([#&#8203;947](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/947))
([9f16faf](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/9f16fafa0f757650c423567b2057683b284a88ec))

###
[`v2.21.1`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.21.1)

[Compare
Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.21.0...v2.21.1)

##### Bug Fixes

- **deps:** update dependency concurrently to v9
([#&#8203;848](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/848))
([5a52eaf](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/5a52eaf77db3403b249a1cf30c0eb1bbc1f10671))

###
[`v2.21.0`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.21.0)

[Compare
Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.20.6...v2.21.0)

##### Features

- **release:** v7.14.0 release
([#&#8203;942](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/942))
([cd3c9a4](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/cd3c9a4b86de43000ff0f915eb5abb8fc5e86915))

###
[`v2.20.6`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.20.6)

[Compare
Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.20.5...v2.20.6)

##### Bug Fixes

- **deps:** update dependency axios to v1.10.0
([#&#8203;939](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/939))
([0f623cc](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/0f623ccd9de6751b9ae8a7fcdd0bd491807baeac))

###
[`v2.20.5`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.20.5)

[Compare
Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.20.4...v2.20.5)

##### Bug Fixes

- **deps:** update nest monorepo to v11.1.3
([#&#8203;935](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/935))
([2575f55](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/2575f55752012d8442095e76fbea0cfe35a258e8))

###
[`v2.20.4`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.20.4)

[Compare
Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.20.3...v2.20.4)

##### Bug Fixes

- **deps:** update dependency glob to v11
([#&#8203;904](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/904))
([7b8ac55](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/7b8ac55ace0f2d803f80ee125ff301735a0dcb7f))

###
[`v2.20.3`](https://redirect.github.com/OpenAPITools/openapi-generator-cli/releases/tag/v2.20.3)

[Compare
Source](https://redirect.github.com/OpenAPITools/openapi-generator-cli/compare/v2.20.2...v2.20.3)

##### Bug Fixes

- **deps:** update dependency glob to v10
([#&#8203;933](https://redirect.github.com/OpenAPITools/openapi-generator-cli/issues/933))
([a6b3d6c](https://redirect.github.com/OpenAPITools/openapi-generator-cli/commit/a6b3d6c93be95eb3fedfaa5789b5556a64fb2c5a))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - "every 2nd week starting on the 2 week
of the year before 4am on Monday" (UTC), Automerge - At any time (no
schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/bitwarden/sdk-internal).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MS43MS4xIiwidXBkYXRlZEluVmVyIjoiNDEuOTcuMTAiLCJ0YXJnZXRCcmFuY2giOiJtYWluIiwibGFiZWxzIjpbXX0=-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Daniel García <[email protected]>
This adds two custom dylint lint.

- `error_suffix`: Requires all types that implements `Error` ends with
an `Error` suffix.
- `error_enum`: Forbids ending enum error variants with `Error`.
Wraps up the b64 migration.
We removed the ability to throw `VaultLocked` a while back. This removes
the actual error struct and any place it's used in.
repository: &dyn Repository<Cipher>,
) -> Result<Vec<CipherView>, GetCipherError> {
let ciphers = repository.list().await?;
let views = store.decrypt_list(&ciphers)?;

Choose a reason for hiding this comment

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

Would it be better to use decrypt_list_failures here to avoid blocking when only some of them fail to decrypt?

Choose a reason for hiding this comment

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

Thanks for adding list_ciphers_with_failures! Do you think we still need the list_ciphers for any use cases, or could we remove it altogether?

Copy link

codecov bot commented Sep 16, 2025

Codecov Report

❌ Patch coverage is 78.29648% with 265 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.08%. Comparing base (b5d27e4) to head (ed2f8e7).
⚠️ Report is 8 commits behind head on main.

Files with missing lines Patch % Lines
...bitwarden-vault/src/cipher/cipher_client/create.rs 85.35% 46 Missing ⚠️
crates/bitwarden-vault/src/cipher/login.rs 47.05% 36 Missing ⚠️
...s/bitwarden-vault/src/cipher/cipher_client/edit.rs 94.46% 33 Missing ⚠️
...es/bitwarden-vault/src/cipher/cipher_client/get.rs 0.00% 33 Missing ⚠️
...tes/bitwarden-vault/src/cipher/cipher_view_type.rs 48.27% 30 Missing ⚠️
crates/bitwarden-vault/src/cipher/identity.rs 0.00% 22 Missing ⚠️
crates/bitwarden-vault/src/cipher/field.rs 0.00% 15 Missing ⚠️
crates/bitwarden-vault/src/cipher/card.rs 0.00% 10 Missing ⚠️
crates/bitwarden-vault/src/cipher/cipher.rs 84.12% 10 Missing ⚠️
crates/bitwarden-vault/src/cipher/secure_note.rs 0.00% 10 Missing ⚠️
... and 3 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #455      +/-   ##
==========================================
- Coverage   78.10%   78.08%   -0.02%     
==========================================
  Files         283      291       +8     
  Lines       27628    28885    +1257     
==========================================
+ Hits        21579    22556     +977     
- Misses       6049     6329     +280     

☔ 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.

@nikwithak
Copy link

Okay I think I got everything @Hinton @shane-melton - a bit of a refactor with the recent commits, so please look carefully to make sure I didn't miss anything

@Hinton
Copy link
Member

Hinton commented Oct 6, 2025

I think you only updated edit and forgot about create?

Comment on lines 304 to 306
let password_history = request.generate_password_history(&original_cipher_view);
let enc_password_history =
password_history.encrypt_composite(&mut key_store.context(), request.key_identifier())?;
Copy link
Member

Choose a reason for hiding this comment

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

I think if you want a nicer interface for this you can create a internal struct that encapsulates the outside data.

Choose a reason for hiding this comment

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

If we were re-using it elsewhere I think that would make sense, but since the need for it is isolated to this one function, I'd prefer to leave it as-is if you're fine with it.

Copy link
Member

Choose a reason for hiding this comment

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

The problem is that both CipherEditRequest and CompositeEncryptable are public. Which means that anyone (both internal to the vault crate but also externally) can call encrypt_composite on it. With the current logic you get back a CipherEditRequest which someone might believe they can post to our API. Without knowing that it lacks several required fields.

If it was just internal misuse I would be a bit less concerned but I could imagine someone calling encrypt on CipherEditRequest.

Encapsulating it in an internal struct prevents this sort of misuse. It's not the biggest thing but encoding this into the types prevents this from ever occurring.

Choose a reason for hiding this comment

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

Yes, makes perfect sense. I added a CipherEditRequestInternal, and modified the password history function to update it directly (rather than return the result). I also changed the password history tests to test on the output of CipherEditRequestInternal::new to make sure it gets set properly during the conversion.

Choose a reason for hiding this comment

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

@Hinton I took this approach for CipherCreateRequest too, since we had a prior discussion about flagging key as something the consumer shouldn't set - with this new approach, we have the same protections around that field on create.

@nikwithak nikwithak requested a review from a team as a code owner October 7, 2025 21:56
@nikwithak
Copy link

I think you only updated edit and forgot about create?

Nice catch - I updated type_data: Option<CipherViewType> -> r#type: CipherViewType. I did away with the Default implementation as well in favor of just updating the test generator function, to avoid making assumptions about the CipherType.

I also added in the wasm_bindgen attributes to the CiphersClient::edit and CiphersClient::create with this update.

@nikwithak nikwithak requested a review from Hinton October 7, 2025 22:19
@coroiu coroiu removed their request for review October 8, 2025 07:40
Copy link
Member

@Hinton Hinton left a comment

Choose a reason for hiding this comment

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

I think the two visbility issues are the only blockers now.,

}
}

#[allow(missing_docs)]
Copy link
Member

@Hinton Hinton Oct 8, 2025

Choose a reason for hiding this comment

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

issue: Should the methods here be public?

If yes: Please document them.
If no: Please lower the visibility and remove the allow(missing_docs)

I think no since we don't want people to manually modify the history.

Choose a reason for hiding this comment

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

Updated to pub(crate)


/// Extension trait to provide type-safe accessors for the different cipher view types.
#[allow(private_bounds)]
pub trait CipherViewTypeExt
Copy link
Member

Choose a reason for hiding this comment

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

question: Does this need to be public? If not you can lower the visibility and remove the allow. You can probably also get rid of the private trait.

Choose a reason for hiding this comment

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

I did away with this trait altogether - since we no longer have Option<CipherViewType> in the structs, it sin't needed. I just implemented those functions on CipherViewType directly.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

@nikwithak nikwithak requested a review from Hinton October 9, 2025 03:07
Copy link

claude bot commented Oct 9, 2025

Claude finished @gbubemismith's task —— View job


Code Review: Migrate Basic Cipher Create, Edit, and Get Operations to SDK

Overall Assessment

This is a substantial and well-structured PR that successfully migrates cipher CRUD operations to the SDK. The code demonstrates good architecture with proper separation of concerns, robust error handling, and comprehensive testing. There are several strengths worth highlighting and a few areas for improvement.

🎯 Strengths

Architecture & Design

  • Clean separation: Operations are properly split into separate modules (create.rs, edit.rs, get.rs)
  • Type safety: Good use of Rust's type system with proper error variants and structured data
  • Enum-based design: The new CipherViewType enum provides better type safety than the previous flattened structure

Security Implementation

  • Cipher key encryption: Proper implementation of cipher key generation and encryption with feature flag support
  • URI checksums: Correctly implemented URI checksum generation for login items
  • FIDO2 re-encryption: Handles FIDO2 credential re-encryption when cipher keys change
  • Password history: Comprehensive password history tracking with proper limits and field change detection

Error Handling

  • Comprehensive error types: Well-defined error enums with proper error propagation
  • Graceful degradation: The decrypt_list_with_failures approach handles partial decryption failures gracefully

⚠️ Areas for Improvement

1. Public API Surface (High Priority)

Issue: Several methods and structs are marked as public but shouldn't be exposed to external consumers.

Files affected:

  • password_history.rs:92-105 - new_password and new_field methods
  • cipher_view_type.rs:34-104 - Helper methods marked with #[allow(unused)]

Recommendation: Make these methods pub(crate) or private to prevent misuse.

2. Documentation (Medium Priority)

Issue: Missing documentation on several public APIs.

Files affected:

  • create.rs:59 - key field needs documentation about being internal-only
  • edit.rs:54 - CipherEditRequest struct needs documentation
  • Various public methods lack comprehensive documentation

Recommendation: Add comprehensive documentation, especially for public APIs that will be used by clients.

3. Code Organization (Medium Priority)

Issue: The CipherEditRequestInternal struct duplicates some logic and could be better encapsulated.

Location: edit.rs:103-140

Recommendation: Consider making the encryption implementation private to prevent external misuse, as noted in reviewer feedback.

4. Test Coverage Gaps (Medium Priority)

Issue: Codecov shows 78.14% patch coverage with 264 lines missing coverage.

Key areas lacking coverage:

  • cipher_view_type.rs - 30 missing lines (48.27% coverage)
  • get.rs - 33 missing lines (0% coverage)
  • Various edge cases in cipher type handling

Recommendation: Add tests for the uncovered code paths, especially error conditions and edge cases.

🔧 Technical Implementation Review

Create Operations (create.rs)

Strengths:

  • Proper cipher key generation with feature flag support
  • Comprehensive encryption implementation
  • Good test coverage with mocked API calls

⚠️ Considerations:

  • URI checksum generation is correctly implemented
  • Encrypted_for field is properly set internally

Edit Operations (edit.rs)

Strengths:

  • Sophisticated password history tracking
  • Handles both login passwords and hidden field changes
  • Proper revision date management
  • Excellent test coverage with multiple scenarios

⚠️ Considerations:

  • Complex password history logic is well-tested but could benefit from more edge case coverage
  • The intermediary CipherEditRequestInternal struct is a good design choice for safety

Get Operations (get.rs)

Strengths:

  • Clean, simple implementation
  • Proper error handling with ItemNotFoundError

⚠️ Considerations:

  • Very low test coverage (0% according to Codecov)
  • Could benefit from additional tests for error conditions

🔍 Security Review

The security implementation appears sound:

  1. Encryption patterns: Follows established patterns for symmetric encryption
  2. Key management: Proper use of cipher keys with feature flag support
  3. Data integrity: URI checksums and proper FIDO2 handling
  4. History tracking: Secure password history with proper limits

📝 Recommendations

High Priority

  1. Reduce public API surface - Make internal helper methods private
  2. Add missing documentation - Especially for client-facing APIs

Medium Priority

  1. Improve test coverage - Focus on get.rs and edge cases
  2. Consider API ergonomics - The conversion from CipherView to CipherEditRequest could be smoother

Low Priority

  1. Code organization - Consider if some complex logic could be extracted into smaller, focused functions

🎉 Conclusion

This is a solid implementation that successfully migrates cipher operations to the SDK while maintaining security and adding useful features like password history tracking. The code demonstrates good Rust practices and thorough testing. With the suggested improvements around API visibility and test coverage, this will be a robust foundation for client applications.

The reviewers' feedback has been well-addressed, and the implementation follows Bitwarden's established patterns for encryption and data handling.


Copy link

sonarqubecloud bot commented Oct 9, 2025

Copy link
Member

@Hinton Hinton left a comment

Choose a reason for hiding this comment

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

Looks good to me, I think you can simplify the internal structs and just wrap the request.

Comment on lines +63 to +73
struct CipherCreateRequestInternal {
organization_id: Option<OrganizationId>,
folder_id: Option<FolderId>,
name: String,
notes: Option<String>,
favorite: bool,
reprompt: CipherRepromptType,
r#type: CipherViewType,
fields: Vec<FieldView>,
key: Option<EncString>,
}
Copy link
Member

Choose a reason for hiding this comment

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

suggestion: I think we can just wrap the public request?

Suggested change
struct CipherCreateRequestInternal {
organization_id: Option<OrganizationId>,
folder_id: Option<FolderId>,
name: String,
notes: Option<String>,
favorite: bool,
reprompt: CipherRepromptType,
r#type: CipherViewType,
fields: Vec<FieldView>,
key: Option<EncString>,
}
struct CipherCreateRequestInternal {
request: CipherCreateRequest,
key: Option<EncString>,
}

Comment on lines +107 to +118
organization_id: Option<OrganizationId>,
folder_id: Option<FolderId>,
favorite: bool,
reprompt: CipherRepromptType,
name: String,
notes: Option<String>,
fields: Vec<FieldView>,
r#type: CipherViewType,
revision_date: DateTime<Utc>,
archived_date: Option<DateTime<Utc>>,
password_history: Vec<PasswordHistoryView>,
key: Option<EncString>,
Copy link
Member

Choose a reason for hiding this comment

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

suggestion: Wrap with the request and you should be able to avoid some of the duplicate code?

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.

8 participants