Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 203 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
# Bitwarden Directory Connector

Comment thread
theMickster marked this conversation as resolved.
## Project Overview

Directory Connector is a TypeScript application that synchronizes users and groups from directory services to Bitwarden organizations. It provides both a desktop GUI (built with Angular and Electron) and a CLI tool (bwdc).

**Supported Directory Services:**

- LDAP (Lightweight Directory Access Protocol) - includes Active Directory and general LDAP servers
- Microsoft Entra ID (formerly Azure Active Directory)
- Google Workspace
- Okta
- OneLogin

**Technologies:**

- TypeScript
- Angular (GUI)
- Electron (Desktop wrapper)
- Node
- Jest for testing

## Code Architecture & Structure

### Directory Organization

```
src/
โ”œโ”€โ”€ abstractions/ # Interface definitions (e.g., IDirectoryService)
โ”œโ”€โ”€ services/ # Business logic implementations for directory services, sync, auth
โ”œโ”€โ”€ models/ # Data models (UserEntry, GroupEntry, etc.)
โ”œโ”€โ”€ commands/ # CLI command implementations
โ”œโ”€โ”€ app/ # Angular GUI components
โ””โ”€โ”€ utils/ # Test utilities and fixtures

src-cli/ # CLI-specific code (imports common code from src/)

jslib/ # Legacy folder structure (mix of deprecated/unused and current code - new code should not be added here)
```

### Key Architectural Patterns

1. **Abstractions = Interfaces**: All interfaces are defined in `/abstractions`
2. **Services = Business Logic**: Implementations live in `/services`
3. **Directory Service Pattern**: Each directory provider implements `IDirectoryService` interface
4. **Separation of Concerns**: GUI (Angular app) and CLI (commands) share the same service layer

## Development Conventions

### Code Organization

**File Naming:**

- kebab-case for files: `ldap-directory.service.ts`
- Descriptive names that reflect purpose

**Class/Function Naming:**

- PascalCase for classes and interfaces
- camelCase for functions and variables
- Descriptive names that indicate purpose

**File Structure:**

- Keep files focused on single responsibility
- Create new service files for distinct directory integrations
- Separate models into individual files when complex

### TypeScript Conventions

**Import Patterns:**

- Use path aliases (`@/`) for project imports
- `@/` - project root
- `@/jslib/` - jslib folder
- ESLint enforces alphabetized import ordering with newlines between groups

**Type Safety:**

- Avoid `any` types - use proper typing or `unknown` with type guards
- Prefer interfaces for contracts, types for unions/intersections
- Use strict null checks - handle `null` and `undefined` explicitly
- Leverage TypeScript's type inference where appropriate

**Configuration:**

- Use configuration files or environment variables
- Never hardcode URLs or configuration values

## Security Best Practices

**Credential Handling:**

- Never log directory service credentials, API keys, or tokens
- Use secure storage mechanisms for sensitive data
- Credentials should never be hardcoded
- Store credentials encrypted, never in plain text

**Sensitive Data:**

- User and group data from directories should be handled securely
- Avoid exposing sensitive information in error messages
- Sanitize data before logging
- Be cautious with data persistence

**Input Validation:**

- Validate and sanitize data from external directory services
- Check for injection vulnerabilities (LDAP injection, etc.)
- Validate configuration inputs from users

**API Security:**

- Ensure authentication flows are implemented correctly
- Verify SSL/TLS is used for all external connections
- Check for secure token storage and refresh mechanisms

## Error Handling

**Best Practices:**

1. **Try-catch for async operations** - Always wrap external API calls
2. **Meaningful error messages** - Provide context for debugging
3. **Error propagation** - Don't swallow errors silently
4. **User-facing errors** - Separate user messages from developer logs

## Performance Best Practices

**Large Dataset Handling:**

- Use pagination for large user/group lists
- Avoid loading entire datasets into memory at once
- Consider streaming or batch processing for large operations

**API Rate Limiting:**

- Respect rate limits for Microsoft Graph API, Google Admin SDK, etc.
- Consider batching large API calls where necessary

**Memory Management:**

- Close connections and clean up resources
- Remove event listeners when components are destroyed
- Be cautious with caching large datasets

## Testing

**Framework:**

- Jest with jest-preset-angular
- jest-mock-extended for type-safe mocks with `mock<Type>()`

**Test Organization:**

- Tests colocated with source files
- `*.spec.ts` - Unit tests for individual components/services
- `*.integration.spec.ts` - Integration tests against live directory services
- Test helpers located in `utils/` directory

**Test Naming:**

- Descriptive, human-readable test names
- Example: `'should return empty array when no users exist in directory'`

**Test Coverage:**

- New features must include tests
- Bug fixes should include regression tests
- Changes to core sync logic or directory specific logic require integration tests

**Testing Approach:**

- **Unit tests**: Mock external API calls using jest-mock-extended
- **Integration tests**: Use live directory services (Docker containers or configured cloud services)
- Focus on critical paths (authentication, sync, data transformation)
- Test error scenarios and edge cases (empty results, malformed data, connection failures), not just happy paths

## Directory Service Patterns

### IDirectoryService Interface

All directory services implement this core interface with methods:

- `getUsers()` - Retrieve users from directory and transform them into standard objects
- `getGroups()` - Retrieve groups from directory and transform them into standard objects
- Connection and authentication handling

### Service-Specific Implementations

Each directory service has unique authentication and query patterns:

- **LDAP**: Direct LDAP queries, bind authentication
- **Microsoft Entra ID**: Microsoft Graph API, OAuth tokens
- **Google Workspace**: Google Admin SDK, service account credentials
- **Okta/OneLogin**: REST APIs with API tokens

## References

- [Architectural Decision Records (ADRs)](https://contributing.bitwarden.com/architecture/adr/)
- [Contributing Guidelines](https://contributing.bitwarden.com/contributing/)
- [Code Style](https://contributing.bitwarden.com/contributing/code-style/)
- [Security Whitepaper](https://bitwarden.com/help/bitwarden-security-white-paper/)
- [Security Definitions](https://contributing.bitwarden.com/architecture/security/definitions)
27 changes: 27 additions & 0 deletions .claude/prompts/review-code.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Please review this pull request with a focus on:

- Code quality and best practices
- Potential bugs or issues
- Security implications
- Performance considerations

Note: The PR branch is already checked out in the current working directory.

Provide a comprehensive review including:

- Summary of changes since last review
- Critical issues found (be thorough)
- Suggested improvements (be thorough)
- Good practices observed (be concise - list only the most notable items without elaboration)
- Action items for the author
- Leverage collapsible <details> sections where appropriate for lengthy explanations or code
snippets to enhance human readability

When reviewing subsequent commits:

- Track status of previously identified issues (fixed/unfixed/reopened)
- Identify NEW problems introduced since last review
- Note if fixes introduced new issues

IMPORTANT: Be comprehensive about issues and improvements. For good practices, be brief - just note
what was done well without explaining why or praising excessively.
5 changes: 5 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@
**/*.dockerignore @bitwarden/team-appsec @bitwarden/dept-bre
**/entrypoint.sh @bitwarden/team-appsec @bitwarden/dept-bre
**/docker-compose.yml @bitwarden/team-appsec @bitwarden/dept-bre

# Claude related files
.claude/ @bitwarden/team-ai-sme
.github/workflows/respond.yml @bitwarden/team-ai-sme
.github/workflows/review-code.yml @bitwarden/team-ai-sme
28 changes: 28 additions & 0 deletions .github/workflows/respond.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Respond

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]

permissions: {}

jobs:
respond:
name: Respond
uses: bitwarden/gh-actions/.github/workflows/_respond.yml@main
secrets:
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
permissions:
actions: read
contents: write
id-token: write
issues: write
pull-requests: write
20 changes: 20 additions & 0 deletions .github/workflows/review-code.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Code Review

on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]

permissions: {}

jobs:
review:
name: Review
uses: bitwarden/gh-actions/.github/workflows/_review-code.yml@main
secrets:
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
permissions:
contents: read
id-token: write
pull-requests: write
Loading