* Add devclarity commands * added doc and skills * Added cipher type skill * Refined the cipher type skills a bit * core models and enum * Wire BankAccount into cipher container classes * Add BankAccount icon(incomplete), vault filters, and shared UI components * Localization keys * Add BankAccount into web vault UI * Add BankAccount into browser extension UI * Add BankAccount into desktop vault UI * Add BankAccount support to CLI * copy actions * Remove .claude/commands files from branch * Updated to match vault/PM-32687-cipher-type-skill * update bank account copy options on web * add copy options for bank account on browser * update bank account copy fields for both versions of the vault * update `hasBankAccount` logic to consider all fields * add PIN and Account Number to protected fields for reprompt service * update bank account section to have readonly properties * localize bank account view - account type * remove duplicate import * add events for bank account * migrate form field to use content children to allow for OnPush consumers to update fields * fix strict typings * fix failing tests from bank account changes * display all bank account details for the cli * add bank icon * add copy option for iban * remove bank account from cipher menu * update bank account implementation based on main * address local claude feedback * address the fixme * local code review changes * update SDK and fix BankAccount adjacent typings * make IBAN and SWIFT fields hidden by default * clean up encrypted string tests * add IBAN and Swift to protected fields * fix test * add BankAccount to cipher-types.md * remove filtering for cli commands --------- Co-authored-by: Patrick Honkonen <phonkonen@bitwarden.com> Co-authored-by: Nick Krantz <nick@livefront.com> Co-authored-by: Nick Krantz <125900171+nick-livefront@users.noreply.github.com>
26 KiB
Cipher Types Reference
A guide for engineers adding or modifying a cipher type in the Bitwarden clients monorepo.
1. Overview
A CipherType is a frozen const object (following ADR-0025) with integer values 1-5:
| Value | Name |
|---|---|
| 1 | Login |
| 2 | SecureNote |
| 3 | Card |
| 4 | Identity |
| 5 | SshKey |
| 6 | BankAccount |
Key file: libs/common/src/vault/enums/cipher-type.ts
Helper functions (same file):
| Function | Purpose |
|---|---|
toCipherTypeName |
Returns the string key name for a CipherType value |
isCipherType |
Type guard - returns true if a value is a valid CipherType |
toCipherType |
Converts an unknown value (including string) to CipherType |
2. The Five-Layer Model Stack
Every cipher type requires classes at five layers. The table below uses SshKey as the canonical example.
| Layer | Purpose | SshKey Example Path |
|---|---|---|
| API | Raw API response shape | libs/common/src/vault/models/api/ssh-key.api.ts |
| Data | Serializable storage format | libs/common/src/vault/models/data/ssh-key.data.ts |
| Domain | Encrypted business object | libs/common/src/vault/models/domain/ssh-key.ts |
| View | Decrypted object for UI | libs/common/src/vault/models/view/ssh-key.view.ts |
| Export | Import/export serialization | libs/common/src/models/export/ssh-key.export.ts |
Data flow: API → Data → Domain (encrypted) → View (decrypted) → Export
Base class: All view models extend ItemView (libs/common/src/vault/models/view/item.view.ts) which requires a subTitle getter. Domain models extend Domain.
3. Container Classes (Switch Statement Catalog)
These container classes have switch statements on CipherType that must receive a new case for each new type.
| Class / File | Methods with switches |
|---|---|
CipherData - libs/common/src/vault/models/data/cipher.data.ts |
Constructor |
Cipher - libs/common/src/vault/models/domain/cipher.ts |
Constructor, decrypt(), toCipherData(), fromJSON(), toSdkCipher(), fromSdkCipher() |
CipherView - libs/common/src/vault/models/view/cipher.view.ts |
item getter, fromJSON(), fromSdkCipherView(), getSdkCipherViewType(), toSdkCipherView() |
CipherRequest - libs/common/src/vault/models/request/cipher.request.ts |
Constructor |
CipherResponse - libs/common/src/vault/models/response/cipher.response.ts |
Constructor (conditional property instantiation, not a switch) |
CipherExport - libs/common/src/models/export/cipher.export.ts |
toView(), toDomain(), build() (constructor) |
CipherService - libs/common/src/vault/services/cipher.service.ts |
encryptCipherData() (private) |
4. UI Components
4a. Form Sections
Each cipher type has a dedicated form section component in:
libs/vault/src/cipher-form/components/
| Type | Directory |
|---|---|
| Login | login-details-section/ |
| Card | card-details-section/ |
| Identity | identity/ |
| SshKey | sshkey-section/ |
| BankAccount | bank-account-section/ |
Container: The cipher form parent that wires these together:
libs/vault/src/cipher-form/components/cipher-form.component.tslibs/vault/src/cipher-form/components/cipher-form.component.htmllibs/vault/src/cipher-form/cipher-form-container.ts
Shared sections (not type-specific but may need updates):
autofill-options/- Login URIsadditional-options/- Notescustom-fields/- Custom fieldsattachments/- File attachmentsitem-details/- Name, folder, organizationcipher-generator/- Password/username generationnew-item-nudge/- New item creation nudge
4b. View Sections
Each cipher type has a dedicated view section component in:
libs/vault/src/cipher-view/
| Type | Directory |
|---|---|
| Login | login-credentials/ |
| Card | card-details/ |
| Identity | view-identity-sections/ |
| SshKey | sshkey-sections/ |
| BankAccount | bank-account-sections/ |
Container:
libs/vault/src/cipher-view/cipher-view.component.tslibs/vault/src/cipher-view/cipher-view.component.html
4c. Shared Touchpoints
| Concern | File(s) |
|---|---|
| Icon builder | libs/common/src/vault/icon/build-cipher-icon.ts (switch on CipherType) |
| Vault filter model | libs/vault/src/models/vault-filter.model.ts |
| Filter function | libs/vault/src/models/filter-function.ts |
| Web type filter | apps/web/src/app/vault/individual-vault/vault-filter/ |
| Desktop type filter | apps/desktop/src/vault/app/vault/vault-filter/filters/type-filter.component.ts |
| Desktop v3 filter | apps/desktop/src/vault/app/vault-v3/vault-filter/filters/type-filter.component.ts |
| Angular lib filter | libs/angular/src/vault/vault-filter/components/type-filter.component.ts |
| New item nudge | libs/vault/src/cipher-form/components/new-item-nudge/new-item-nudge.component.ts |
5. Localization
Three apps maintain independent locale files. Each new cipher type needs i18n keys for the type label and any type-specific field labels.
| App | English locale file |
|---|---|
| Web | apps/web/src/locales/en/messages.json |
| Desktop | apps/desktop/src/locales/en/messages.json |
| Browser | apps/browser/src/_locales/en/messages.json |
| CLI | apps/cli/src/locales/en/messages.json |
Translations for non-English locales are handled separately via Crowdin. Only add keys to the
enfiles.
6. CLI
| Concern | File |
|---|---|
| Cipher response model | apps/cli/src/vault/models/cipher.response.ts |
| Get command | apps/cli/src/commands/get.command.ts |
| Create command | apps/cli/src/vault/create.command.ts |
| Delete command | apps/cli/src/vault/delete.command.ts |
| Restricted types svc | apps/cli/src/vault/services/cli-restricted-item-types.service.ts |
| Restricted types spec | apps/cli/src/vault/services/cli-restricted-item-types.service.spec.ts |
7. Import/Export
| Concern | File |
|---|---|
| Type-specific export class | libs/common/src/models/export/ssh-key.export.ts (example) |
| Main export container | libs/common/src/models/export/cipher.export.ts |
| CSV export service | libs/tools/export/vault-export/vault-export-core/src/services/base-vault-export.service.ts |
| Individual vault export | libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.ts |
| Org vault export | libs/tools/export/vault-export/vault-export-core/src/services/org-vault-export.service.ts |
| Import service | libs/importer/src/services/import.service.ts |
| Base importer | libs/importer/src/importers/base-importer.ts |
The CSV export service (
base-vault-export.service.ts) currently only exports Login and SecureNote types. New types may need explicit CSV column mappings or may only support JSON export.
8. SDK Integration
The clients repo bridges to @bitwarden/sdk-internal via mapper classes and toSdk*/fromSdk* methods on domain and view models.
| Concern | File |
|---|---|
| Record mapper | libs/common/src/vault/models/domain/cipher-sdk-mapper.ts |
| Domain SDK methods | libs/common/src/vault/models/domain/cipher.ts (toSdkCipher, fromSdkCipher) |
| View SDK methods | libs/common/src/vault/models/view/cipher.view.ts (toSdkCipherView, fromSdkCipherView, getSdkCipherViewType) |
| Type-specific domain SDK | libs/common/src/vault/models/domain/ssh-key.ts (toSdkSshKey, fromSdkSshKey) |
| Type-specific view SDK | libs/common/src/vault/models/view/ssh-key.view.ts (toSdkSshKeyView, fromSdkSshKeyView) |
| SDK cipher service | libs/common/src/vault/services/cipher-sdk.service.ts |
| SDK abstraction | libs/common/src/vault/abstractions/cipher-sdk.service.ts |
Pattern: Each type-specific domain model needs toSdk<Type>() and static fromSdk<Type>() methods. Each view model needs toSdk<Type>View() and static fromSdk<Type>View() methods. The SDK types are imported from @bitwarden/sdk-internal.
9. Browser Extension (Autofill)
Only Login, Card, and Identity currently support autofill. SecureNote and SshKey do not participate in autofill.
Key autofill files that reference CipherType:
| Concern | File |
|---|---|
| Autofill service | apps/browser/src/autofill/services/autofill.service.ts |
| Autofill service abstraction | apps/browser/src/autofill/services/abstractions/autofill.service.ts |
| Overlay background | apps/browser/src/autofill/background/overlay.background.ts |
| Notification background | apps/browser/src/autofill/background/notification.background.ts |
| Context menu handler | apps/browser/src/autofill/browser/context-menu-clicked-handler.ts |
| Cipher context menu | apps/browser/src/autofill/browser/cipher-context-menu-handler.ts |
| Main context menu | apps/browser/src/autofill/browser/main-context-menu-handler.ts |
| Overlay content service | apps/browser/src/autofill/services/autofill-overlay-content.service.ts |
| Inline menu list | apps/browser/src/autofill/overlay/inline-menu/pages/list/autofill-inline-menu-list.ts |
| Autofill enum types | apps/browser/src/autofill/enums/autofill-overlay.enum.ts |
| Content cipher types | apps/browser/src/autofill/content/components/cipher/types.ts |
If a new cipher type should support autofill, these files will need updates. Otherwise, no changes are needed.
10. Cross-Repository Dependencies
Adding a new cipher type is a cross-repo effort spanning three repositories.
SDK (bitwarden/sdk)
High-level changes needed:
- Add a Rust enum variant to the
CipherTypeenum - Create type-specific Rust structs (encrypted + decrypted)
- Implement serde (de)serialization
- Implement
Encryptable/Decryptabletraits - Add WASM bindings so the TypeScript types are generated
- Bump the SDK version
Server (bitwarden/server)
High-level changes needed:
- Add a C# enum value to
src/Core/Vault/Enums/CipherType.cs - Database migration (if schema changes are needed)
- Domain model and DTOs (see file list below)
- Validation rules for the new type
- Event logging for audit trail
- Feature flag and sync controller version gating (see below)
Server files to create
| File | Purpose |
|---|---|
src/Core/Vault/Models/Data/Cipher<Type>Data.cs |
Core data model (extends CipherData) |
src/Api/Vault/Models/Cipher<Type>Model.cs |
API model with [EncryptedString] validation |
test/Api.Test/Vault/Models/Cipher<Type>ModelTests.cs |
Unit tests for the API model |
util/Seeder/Factories/<Type>CipherSeeder.cs |
Dev/test seeder factory for the new type |
Server files to modify
| File | Change |
|---|---|
src/Core/Vault/Enums/CipherType.cs |
Add enum value |
src/Core/Constants.cs |
Add <Type>CipherMinimumVersion constant and feature flag key |
src/Api/Vault/Models/Request/CipherRequestModel.cs |
Add property + ToCipher<Type>Data() method + switch case |
src/Api/Vault/Models/Response/CipherResponseModel.cs |
Add property + deserialization case |
src/Core/Vault/Services/Implementations/CipherService.cs |
Add serialize/deserialize cases |
src/Api/Vault/Controllers/SyncController.cs |
Add version gate to FilterUnsupportedCipherTypes() |
util/Seeder/Models/CipherViewDto.cs |
Add view DTO + type constant |
util/Seeder/Models/EncryptedCipherDto.cs |
Add encrypted DTO |
util/Seeder/Models/EncryptedCipherDtoExtensions.cs |
Add To<Type>Data() mapping |
test/Api.Test/Vault/Controllers/SyncControllerTests.cs |
Add tests for version/flag gating |
Sync controller version gating
The SyncController filters out cipher types that the requesting client doesn't support. This prevents older clients from receiving types they can't handle. The filter lives in the private method FilterUnsupportedCipherTypes().
Each new cipher type needs two gates in Constants.cs:
- Minimum version constant (e.g.,
BankAccountCipherMinimumVersion = "2026.2.0") — clients older than this version won't receive the cipher type. - Feature flag key (e.g.,
FeatureFlagKeys.VaultBankAccount) — allows disabling the type entirely during rollout.
The gating logic is: a cipher type is filtered out if clientVersion < minimumVersion OR featureFlag is disabled. Both conditions must pass for the type to be returned.
Note: SshKey uses a single gate (version only), while BankAccount uses a dual gate (version + feature flag). Prefer the dual-gate pattern for new types so rollout can be controlled server-side.
[Obsolete("Use Data instead.")] pattern
The server is migrating toward a single Data JSON string property on request/response models. Per-type properties (e.g., SSHKey, BankAccount) are still present for backwards compatibility but are marked [Obsolete("Use Data instead.")]. New types should follow this pattern: add the typed property for older clients, mark it obsolete, and ensure the Data JSON path also works.
The clients repo consumes server API contracts via
CipherResponseand SDK types via@bitwarden/sdk-internal. Coordinate version bumps across all three repos.
11. Restricted Item Types
The RestrictedItemTypesService (libs/common/src/vault/services/restricted-item-types.service.ts) dynamically determines which cipher types an organization restricts via policy. No client code change is typically needed when adding a new type - the service reads the policy configuration from the server.
However, if the new type should appear in the policy configuration UI:
apps/web/src/app/admin-console/organizations/policies/policy-edit-definitions/restricted-item-types.component.tsapps/web/src/app/admin-console/organizations/policies/policy-edit-definitions/restricted-item-types.component.html
CLI restricted types service:
apps/cli/src/vault/services/cli-restricted-item-types.service.ts
12. Linked Fields (Optional)
Linked fields allow custom fields to reference a specific property of a cipher type. Not all types support linked fields (SshKey and SecureNote do not).
Key file: libs/common/src/vault/enums/linked-id-type.enum.ts
Current linked ID const objects:
| Type | Const Object | ID Range |
|---|---|---|
| Login | LoginLinkedId |
100-101 |
| Card | CardLinkedId |
300-305 |
| Identity | IdentityLinkedId |
400-418 |
The union type LinkedIdType = LoginLinkedId | CardLinkedId | IdentityLinkedId must be expanded if the new type supports linked fields.
In the view model, properties that can be linked are decorated with @linkedFieldOption. The view model's linkedFieldOptions map (from ItemView) is populated from these decorators.
13. Tests
| Test Area | File(s) |
|---|---|
| Cipher type enum | libs/common/src/vault/enums/cipher-type.spec.ts |
| Domain model | libs/common/src/vault/models/domain/cipher.spec.ts |
| Domain type-specific (SshKey) | libs/common/src/vault/models/domain/ssh-key.spec.ts |
| View model | libs/common/src/vault/models/view/cipher.view.spec.ts |
| Cipher service | libs/common/src/vault/services/cipher.service.spec.ts |
| Cipher SDK service | libs/common/src/vault/services/cipher-sdk.service.spec.ts |
| Cipher encryption service | libs/common/src/vault/services/default-cipher-encryption.service.spec.ts |
| Icon builder | libs/common/src/vault/icon/build-cipher-icon.spec.ts |
| Export model | libs/common/src/models/export/cipher.export.spec.ts |
| Cipher form component | libs/vault/src/cipher-form/components/cipher-form.component.spec.ts |
| Cipher view component | libs/vault/src/cipher-view/cipher-view.component.spec.ts |
| Restricted types | libs/common/src/vault/services/restricted-item-types.service.spec.ts |
| CLI restricted types | apps/cli/src/vault/services/cli-restricted-item-types.service.spec.ts |
| Import service | libs/importer/src/services/import.service.spec.ts |
| Export services | libs/tools/export/vault-export/vault-export-core/src/services/individual-vault-export.service.spec.ts |
14. Recommended Order of Operations
- Server - Add enum value, domain model, DTOs, validation, feature flag, minimum version constant, and sync controller version gating
- SDK - Add Rust enum variant, type structs, serde, crypto traits, and WASM bindings
- Clients: Core enum - Add value to
CipherTypeinlibs/common/src/vault/enums/cipher-type.ts - Clients: Model stack - Create the 5 model layer files (API, Data, Domain, View, Export)
- Clients: Container switches - Add cases in
CipherData,Cipher,CipherView,CipherRequest,CipherResponse,CipherExport, andCipherService.encryptCipherData() - Clients: SDK bindings - Add
toSdk*/fromSdk*methods on domain and view models; updateCipherRecordMapperif needed - Clients: Localization - Add i18n keys to
en/messages.jsonin web, desktop, browser, and CLI - Clients: Shared UI - Update icon builder, vault filters, and any shared components
- Clients: Per-app UI - Add form section and view section components; wire into container templates
- Clients: Import/Export - Update
CipherExportswitch cases; update CSV export if applicable; update importers - Clients: CLI - Update cipher response model, get/create commands
- Clients: Autofill - Only if the new type participates in autofill (Login/Card/Identity only today)
- Clients: Tests - Add/update specs for all touched files; add type-specific domain and view specs
- Feature flag - Gate the new type behind a feature flag for incremental rollout
15. Complete File Checklist
New files to create
libs/common/src/vault/models/api/<type>.api.tslibs/common/src/vault/models/data/<type>.data.tslibs/common/src/vault/models/domain/<type>.tslibs/common/src/vault/models/domain/<type>.spec.tslibs/common/src/vault/models/view/<type>.view.tslibs/common/src/models/export/<type>.export.tslibs/vault/src/cipher-form/components/<type>-section/(component TS, HTML, spec)libs/vault/src/cipher-view/<type>-sections/(component TS, HTML)
Existing files to modify
Core:
libs/common/src/vault/enums/cipher-type.ts- Add new valuelibs/common/src/vault/enums/cipher-type.spec.ts- Update tests
Container switches:
libs/common/src/vault/models/data/cipher.data.ts- Constructorlibs/common/src/vault/models/domain/cipher.ts- 6 methodslibs/common/src/vault/models/view/cipher.view.ts- 5 methodslibs/common/src/vault/models/request/cipher.request.ts- Constructorlibs/common/src/vault/models/response/cipher.response.ts- Constructorlibs/common/src/models/export/cipher.export.ts- 3 methodslibs/common/src/vault/services/cipher.service.ts-encryptCipherData()
UI:
libs/vault/src/cipher-form/components/cipher-form.component.html- Add sectionlibs/vault/src/cipher-form/components/cipher-form.component.ts- Wire sectionlibs/vault/src/cipher-view/cipher-view.component.html- Add sectionlibs/vault/src/cipher-view/cipher-view.component.ts- Wire sectionlibs/common/src/vault/icon/build-cipher-icon.ts- Add icon case
Localization:
apps/web/src/locales/en/messages.jsonapps/desktop/src/locales/en/messages.jsonapps/browser/src/_locales/en/messages.jsonapps/cli/src/locales/en/messages.json
CLI:
apps/cli/src/vault/models/cipher.response.tsapps/cli/src/commands/get.command.ts
Import/Export:
libs/tools/export/vault-export/vault-export-core/src/services/base-vault-export.service.ts
Linked fields (if applicable):
libs/common/src/vault/enums/linked-id-type.enum.ts
Historical Reference
The BankAccount cipher type (value 6) was the most recently added type and serves as the best template.
Use git log --all --oneline --grep="BankAccount" to find related commits.
SshKey (value 5) is the previous reference implementation:
b18fa68acc- Initial SshKey model stack and container switch additions081fe83d83- SshKey UI components (form and view sections)
Use git log --all --oneline --grep="SshKey" to find additional related commits.