Skip to content
Open
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
8 changes: 8 additions & 0 deletions docs/architecture/adr/0003-observable-data-services.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ Chosen option: **Observable data services**, because
- The work towards a reactive data model will allow us to adopt patterns like NGRX in the future
should it be needed.

:::info Updated Guidance

This ADR remains valid for business logic services, but
[ADR 0029](/architecture/adr/0029-angular-signals) introduces Angular Signals as the preferred
approach over RxJS for view layer code (components, directives, pipes, and UI-coupled services).

:::

### Example

#### Organizations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ as they are expected to always be included in the host -- those services are `IL

## Considered options

- **Ad-hoc usage** - Where we are today, the `TryAdd` overloads are allowed to be used and are used
- **Ad hoc usage** - Where we are today, the `TryAdd` overloads are allowed to be used and are used
occasionally throughout the codebase but they is no outside encouragement to use them.
- **Encourage usage** - Start encouraging usage through team training and encouragement to use them
in code reviews but don't make any automatic check to enforce usage.
Expand Down
80 changes: 80 additions & 0 deletions docs/architecture/adr/0029-angular-signals.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
---
adr: "0029"
status: "Accepted"
date: 2025-11-24
tags: [clients, angular]
---

# 0028 - Adopt Angular Signals for Component State

<AdrTable frontMatter={frontMatter}></AdrTable>

## Context and Problem Statement

Angular has adopted a new reactive primitive, signals. Signals have various improvements over RxJS:
performance, simplicity, and deeper integrations into the rest of the framework.

RxJS will become an optional dependency of Angular. Certain asynchronous workflows will still
benefit from RxJS (signals are synchronous). Furthermore, being a part of the core Angular library,
Angular signals cannot readily be used in non-Angular environments.

As such, Signals should be the default when operating _in the view layer_: components, directives,
pipes, and services that are tightly coupled to the UI/Angular. Services that primarily deal with
business logic should prefer RxJS to maximize portability (or, even better, be moved to the Rust
Copy link
Contributor

@theMickster theMickster Nov 25, 2025

Choose a reason for hiding this comment

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

๐ŸŽจ I am good with the comment that suggests the usage of the Rust SDK.
That being said, I think it is important that an ADR be written to clearly describe that process. I do not currently see one published to our ADR Wiki.

I think it important for a few reasons:
A.) The codifying of the decision and migration plan to the Rust SDK aligns perfectly with our ADR mission statement
B.) Crafting it leaves behind a clear trail for teammates new and old to follow; minimized tribal knowledge around the migration
C.) Claude Code (or other agents) will hopefully be able to leverage the ADR to make suggestions to teammates working in the clients repo to move said business logic to the Rust SDK.

๐Ÿ’ญ@Hinton, @withinfocus, @MGibson1?

SDK).

## Decision

Signal-based APIs (inputs, outputs, child queries) will be required in components and directives via
linting:

- `@Input()` โ†’ `input()`
- `@Output()` โ†’ `output()`
- `@ViewChild`/`@ContentChild` โ†’ `viewChild()`/`contentChild()`

Services tightly coupled to Angular should use signals. Services with non-presentational business
logic should prefer RxJS for portability. Use `toSignal()` and `toObservable()` to bridge between
RxJS and signals when necessary.

## Implementation Plan

New code must use signal-based APIs; existing code will be migrated gradually. Angular provides
automatic code migrations for signal
[inputs](https://angular.dev/reference/migrations/signal-inputs) and
[queries](https://angular.dev/reference/migrations/signal-queries).

Much of `libs/components` was updated using these migrators:
https://github.com/bitwarden/clients/pull/15340

See the
[Angular Modernization Guide](https://contributing.bitwarden.com/contributing/code-style/web/angular-migration-guide/#signals)
for more information.

## Consequences

**Positive:**

- Improved performance and simpler change detection
- Clear path to removing Zone.js dependency
- Better debugging experience
- Aligned with Angular's direction
- Simpler than RxJS for many common use cases

**Negative:**

- Temporary complexity during migration with mixed RxJS/Signals patterns
- Learning curve for team members unfamiliar with signals
- Migration effort required for existing codebase

## Reasons against other options

- Disallow usage of signals and only use RxJS for reactivity.
- This is a non-starter. Signals are being built into Angular.
- Continue the status quo of ad hoc usage.
- Having multiple ways to do the same thing leads to analysis paralysis and complicated code.
- Signals + OnPush change detection provide a clear path to removing Zone.js. With that comes
notable performance and debugging improvements.

## Further reading

- [Angular docs](https://angular.dev/guide/signals)
2 changes: 1 addition & 1 deletion docs/architecture/security/definitions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ be able to do, and what they want to achieve, possibly even not having anything
achieve, just the notion of "I want a secure product".

A formal approach here is needed: to aid in communication and to also provide a clear set of goals
to achieve. This applies both to ad-hoc conversations in which the participants don't yet share a
to achieve. This applies both to ad hoc conversations in which the participants don't yet share a
common understanding of security goals and the assumed attacker, but it also applies to
long-standing assumed security we want to achieve for our clients, communication protocols, and
cryptography. This is not limited to cryptographic topics.
Expand Down
2 changes: 1 addition & 1 deletion docs/contributing/code-style/web/angular.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ component "Organization Reports Module" {
@enduml
```

## Reactivity ([ADR-0003](../../../architecture/adr/0003-observable-data-services.md))
## Reactivity ([ADR-0003](../../../architecture/adr/0003-observable-data-services.md) & [ADR-0029](../../../architecture/adr/0029-angular-signals.md))

We make heavy use of reactive programming using [Angular Signals][signals] & [RxJS][rxjs]. Generally
components should always derive their state reactively from services whenever possible.
Expand Down
Loading