1
0
mirror of https://github.com/bitwarden/browser synced 2026-02-23 16:13:21 +00:00

Adjusted claude.md to have context, but not the kitchen sink

This commit is contained in:
Anders Åberg
2026-01-15 11:44:50 +01:00
parent 2cec30e533
commit 13c2857a28

View File

@@ -1,64 +1,179 @@
# Bitwarden Clients - Claude Code Configuration
# CLAUDE.md
## Project Context Files
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
**Read these files before reviewing to ensure that you fully understand the project and contributing guidelines**
## Overview
1. @README.md
2. @CONTRIBUTING.md
3. @.github/PULL_REQUEST_TEMPLATE.md
### What This Project Does
Bitwarden Clients is a monorepo containing all Bitwarden client applications:
- **Web Vault** - Angular SPA for browser-based password management
- **Browser Extension** - Extensions for Chrome, Firefox, Safari, Edge, Opera
- **Desktop App** - Electron-based desktop application (Windows, macOS, Linux)
- **CLI** - Command-line interface for automation and scripting
All clients share core libraries for business logic, cryptography, and UI components.
### Key Concepts
| Term | Definition |
| ---------------- | --------------------------------------------------------------------- |
| **Cipher** | An encrypted vault item (login, card, identity, secure note, SSH key) |
| **CipherView** | Decrypted representation of a Cipher for display |
| **EncString** | Encrypted string wrapper with encryption type metadata |
| **Vault** | User's encrypted collection of Ciphers |
| **Organization** | Shared vault for team/enterprise password sharing |
| **Collection** | Grouping mechanism for organizing Ciphers within Organizations |
## Build and Development Commands
**Install dependencies** (from repo root):
```bash
npm ci
```
**Run apps in development** (from each app directory):
```bash
# Web vault (apps/web) -- also used for proxying the API calls if you're running a local server
npm run build:bit:dev:watch # Bitwarden licensed version at http://localhost:8080
npm run build:oss:watch # OSS version
# Browser extension (apps/browser)
npm run build:watch:chrome # Chrome/Chromium
npm run build:watch:firefox # Firefox
npm run build:watch:safari # Safari
# Desktop (apps/desktop)
npm run build:main:watch # Build main process
npm run build:renderer:watch # Build renderer (Angular)
npm run electron # Start Electron after building
# CLI (apps/cli)
npm run build:oss:watch
node ./build/bw.js # Run CLI after building
```
**Linting and formatting**:
```bash
npm run lint # Run ESLint + Prettier check
npm run lint:fix # Auto-fix ESLint issues
npm run prettier # Auto-format with Prettier
```
**Testing**:
```bash
npm test # Run all tests across projects
npm test -- --testPathPattern="path/to/test" # Run specific test file
npm test -- --selectProjects=@bitwarden/common # Run tests for specific project
x # In app directories (apps/web, apps/browser, etc.):
x npm test # Run tests for that app
x npm run test:watch # Watch mode
```
**Run single test file** (from root):
```bash
npm test -- libs/common/src/vault/models/cipher.spec.ts
```
**NX commands** (monorepo task runner):
```bash
npx nx test @bitwarden/common # Test specific library
npx nx lint @bitwarden/vault # Lint specific library
npx nx run-many -t test --all # Run all tests
npx nx affected -t test # Test only affected projects
```
## Critical Rules
- **NEVER** use code regions: If complexity suggests regions, refactor for better readability
- **CRITICAL**: new encryption logic should not be added to this repo.
- **NEVER** add new encryption logic to this repo—cryptographic operations belong in the SDK
- **NEVER** send unencrypted vault data to API services
- **NEVER** commit secrets, credentials, or sensitive information.
- **CRITICAL**: Tailwind CSS classes MUST use the `tw-` prefix (e.g., `tw-flex`, `tw-p-4`).
- Missing prefix breaks styling completely.
- **NEVER** log decrypted data, encryption keys, or PII
- No vault data in error messages or console logs
- **CRITICAL**: Tailwind CSS classes MUST use the `tw-` prefix (e.g., `tw-flex`, `tw-p-4`)
- **NEVER** use TypeScript enums—use const objects with type aliases (see pattern below)
- **NEVER** use code regions—refactor for readability instead
- **ALWAYS** Respect configuration files at the root and within each app/library (e.g., `eslint.config.mjs`, `jest.config.js`, `tsconfig.json`).
## Monorepo Architecture
## Mono-Repo Architecture
```
apps/
├── browser/ # Browser extension (Chrome, Firefox, Safari, Edge, Opera)
├── cli/ # Command-line interface
├── desktop/ # Electron desktop app
└── web/ # Web vault (Angular SPA)
This repository is organized as a **monorepo** containing multiple applications and libraries. The
main directories are:
libs/
├── common/ # Core business logic, models, services (shared by all clients)
├── angular/ # Angular-specific abstractions and services
├── components/ # Reusable Angular UI components (CL - Component Library)
├── platform/ # Platform abstractions (crypto, storage, messaging)
├── state/ # State management infrastructure
├── auth/ # Authentication logic
├── vault/ # Vault-specific UI and services
├── key-management/ # Key derivation, rotation, biometrics
├── billing/ # Subscription and payment logic
├── admin-console/ # Organization admin features
├── tools/ # Generator, export, send functionality
└── [team-libs]/ # Team-owned domain libraries
- `apps/` Contains all application projects (e.g., browser, cli, desktop, web). Each app is
self-contained with its own configuration, source code, and tests.
- `libs/` Contains shared libraries and modules used across multiple apps. Libraries are organized
by team name, domain, functionality (e.g., common, ui, platform, key-management).
**Strict boundaries** must be maintained between apps and libraries. Do not introduce
cross-dependencies that violate the intended modular structure. Always consult and respect the
dependency rules defined in `eslint.config.mjs`, `nx.json`, and other configuration files.
## Angular Architecture Patterns
**Observable Data Services (ADR-0003):**
- Services expose RxJS Observable streams for state management
- Components subscribe using `async` pipe (NOT explicit subscriptions in most cases)
Pattern:
```typescript
// Service
private _folders = new BehaviorSubject<Folder[]>([]);
readonly folders$ = this._folders.asObservable();
// Component
folders$ = this.folderService.folders$;
// Template: <div *ngFor="let folder of folders$ | async">
bitwarden_license/ # Licensed features (enterprise, premium)
├── bit-web/
├── bit-browser/
├── bit-cli/
└── bit-common/
```
For explicit subscriptions, MUST use `takeUntilDestroyed()`:
**Import paths**: Use `@bitwarden/common/*`, `@bitwarden/components`, etc. (defined in `tsconfig.base.json`).
**Dependency boundaries**: Libraries cannot import from apps. Apps import from libs. Licensed code extends OSS code.
## Data Models
The codebase uses a layered model pattern:
```
Response (API) → Data (Storage) → Domain (Encrypted) → View (Decrypted)
```
| Layer | Purpose | Example |
| ------------ | ----------------------------- | -------------------------------------- |
| **Response** | API response DTOs | `CipherResponse` |
| **Data** | JSON-serializable for storage | `CipherData` |
| **Domain** | Encrypted business objects | `Cipher` (contains `EncString` fields) |
| **View** | Decrypted for UI display | `CipherView` (contains plain strings) |
**Core Types** (from `libs/common/src/types/guid.ts`):
```typescript
// Branded types for type-safe IDs
type UserId = Opaque<string, "UserId">;
type CipherId = Opaque<string, "CipherId">;
type OrganizationId = Opaque<string, "OrganizationId">;
type CollectionId = Opaque<string, "CollectionId">;
```
## Angular Patterns
**Observable Data Services (ADR-0003)**:
```typescript
// Service exposes Observable streams
private _data$ = new BehaviorSubject<Data[]>([]);
readonly data$ = this._data$.asObservable();
// Component uses async pipe
data$ = this.dataService.data$;
// Template: <div *ngFor="let item of data$ | async">
```
**Subscription cleanup** (required for explicit subscriptions):
```typescript
constructor() {
@@ -66,46 +181,211 @@ constructor() {
}
```
**Angular Signals (ADR-0027):**
**Signals**: Use Angular Signals only in components and presentational services. Use RxJS for cross-client services and complex reactive workflows.
Encourage the use of Signals **only** in Angular components and presentational services.
Use **RxJS** for:
- Services used across Angular and non-Angular clients
- Complex reactive workflows
- Interop with existing Observable-based code
**NO TypeScript Enums (ADR-0025):**
- Use const objects with type aliases instead
- Legacy enums exist but don't add new ones
Pattern:
**No TypeScript Enums (ADR-0025)**:
```typescript
// ✅ DO
// ✅ Correct
export const CipherType = Object.freeze({
Login: 1,
SecureNote: 2,
} as const);
export type CipherType = (typeof CipherType)[keyof typeof CipherType];
// ❌ DON'T
// ❌ Wrong - don't add new enums
enum CipherType {
Login = 1,
SecureNote = 2,
}
```
Example: `/libs/common/src/vault/enums/cipher-type.ts`
**Component Change Detection**: Use `OnPush` change detection strategy for all components.
## State Management
State is managed through `StateProvider` with typed `KeyDefinition`s:
```typescript
// Define state key
const MY_STATE = KeyDefinition.record<MyData>(STATE_DEFINITION, "myKey", {
deserializer: (data) => data,
});
// Use in service
this.state$ = this.stateProvider.getGlobal(MY_STATE).state$;
```
User-scoped state uses `UserKeyDefinition` and requires a `UserId`.
## Feature Flags
Feature flags are defined in `libs/common/src/enums/feature-flag.enum.ts`. Use `ConfigService` to check flags:
```typescript
const enabled = await this.configService.getFeatureFlag(FeatureFlag.MyFlag);
```
Flags MUST be short-lived and removed once fully enabled.
## Testing
### Test Structure
Tests are colocated with source files using `.spec.ts` suffix:
```
libs/common/src/vault/models/domain/cipher.ts
libs/common/src/vault/models/domain/cipher.spec.ts
```
### Test Utilities
| Utility | Location | Purpose |
| ----------------------- | ------------------------------------------ | -------------------------------- |
| `mockEnc()` | `libs/common/spec/utils.ts` | Create mock EncString |
| `makeStaticByteArray()` | `libs/common/spec/utils.ts` | Create deterministic byte arrays |
| `FakeStateProvider` | `libs/common/spec/fake-state-provider.ts` | Mock state management |
| `FakeAccountService` | `libs/common/spec/fake-account-service.ts` | Mock account service |
| `trackEmissions()` | `@bitwarden/core-test-utils` | Track Observable emissions |
### Unit Test Template
```typescript
import { mock, MockProxy } from "jest-mock-extended";
describe("MyService", () => {
let sut: MyService;
let dependency: MockProxy<DependencyService>;
beforeEach(() => {
dependency = mock<DependencyService>();
sut = new MyService(dependency);
});
it("should do something", () => {
dependency.method.mockReturnValue(expected);
const result = sut.doSomething();
expect(result).toEqual(expected);
});
});
```
### Component Test Template
```typescript
import { ComponentFixture, TestBed } from "@angular/core/testing";
describe("MyComponent", () => {
let fixture: ComponentFixture<MyComponent>;
let component: MyComponent;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MyComponent],
providers: [{ provide: MyService, useValue: mock<MyService>() }],
}).compileComponents();
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
});
it("should create", () => {
expect(component).toBeTruthy();
});
});
```
## Code Style & Standards
### Formatting
- **Prettier** for code formatting (run `npm run prettier`)
- **ESLint** for linting (run `npm run lint`)
- Pre-commit hooks enforce formatting
### Naming Conventions
| Type | Convention | Example |
| ------------------- | -------------------------- | ------------------- |
| Files | kebab-case | `cipher.service.ts` |
| Classes | PascalCase | `CipherService` |
| Interfaces | PascalCase (no `I` prefix) | `CipherService` |
| Variables/Functions | camelCase | `getCipher()` |
| Constants | SCREAMING_SNAKE_CASE | `MAX_RETRY_COUNT` |
| Observables | camelCase with `$` suffix | `ciphers$` |
### Import Order
1. External packages (`@angular/*`, `rxjs`, etc.)
2. `@bitwarden/*` packages
3. Relative imports
## Anti-Patterns
### DO
- Use `takeUntilDestroyed()` for subscription cleanup
- Use `OnPush` change detection
- Use const objects instead of enums
- Use branded types (`UserId`, `CipherId`) for IDs
- Use `async` pipe in templates
- Keep components focused and small
- Write unit tests for services
- Use dependency injection
### DON'T
- Add new TypeScript enums
- Add encryption logic (use SDK)
- Log sensitive data (PII, keys, vault data)
- Use Tailwind classes without `tw-` prefix
- Create manual subscriptions without cleanup
- Import from apps in libraries
- Use `any` type without justification
- Skip the View layer for displaying data
- Use code regions
## Troubleshooting
### Common Issues
| Issue | Solution |
| ------------------------------------ | ----------------------------------------------- |
| Build fails with module errors | Run `npm ci` to reinstall dependencies |
| Tests fail with "Cannot find module" | Check `tsconfig.json` paths, run `npx nx reset` |
| Tailwind styles not applying | Ensure `tw-` prefix on all Tailwind classes |
| State not persisting | Verify `KeyDefinition` is correctly configured |
| Encryption errors | Check SDK is properly initialized |
### Debug Tips
**Web**: Use browser DevTools, check Network tab for API calls
**Browser Extension**: Load unpacked extension, use `chrome://extensions` → "Inspect views"
**Desktop**: Use `--inspect` flag, access DevTools via View → Toggle Developer Tools
**CLI**: Add `--debug` flag, use `console.log` for quick debugging
## Component Library
Located in `libs/components/`. Use Storybook for development:
```bash
npm run storybook # Start at http://localhost:6006
npm run build-storybook # Build static Storybook
```
## References
- [Web Clients Architecture](https://contributing.bitwarden.com/architecture/clients)
- [Architectural Decision Records (ADRs)](https://contributing.bitwarden.com/architecture/adr/)
### Official Documentation
- [Clients Architecture](https://contributing.bitwarden.com/architecture/clients)
- [ADRs](https://contributing.bitwarden.com/architecture/adr/)
- [Contributing Guide](https://contributing.bitwarden.com/)
- [Web Clients Setup Guide](https://contributing.bitwarden.com/getting-started/clients/)
- [Code Style](https://contributing.bitwarden.com/contributing/code-style/)
- [Security Whitepaper](https://bitwarden.com/help/bitwarden-security-white-paper/)
### Internal Documentation
- [Security Definitions](https://contributing.bitwarden.com/architecture/security/definitions)
- [Getting Started](https://contributing.bitwarden.com/getting-started/clients/)