Commit Graph

1074 Commits

Author SHA1 Message Date
Bernd Schoolmann
dd31e70cc1
[PM-39259] Migrate auth token key generation to SDK (#21706)
* [PM-39259] Migrate auth to SDK key generation

* Fix login command tests
2026-07-15 06:04:57 -04:00
Ike
1a2f041cb3
[PM-27060] feat: Call SDK for password prelogin (#21777)
feat: call SDK for password prelogin (PM-27060)

- Add PM27060_PasswordPreloginFromSdk feature flag (default off) to gate the new behavior
- Update `DefaultPasswordPreloginService` to call the SDK for prelogin when the flag is enabled, falling back to the existing API-based path otherwise
2026-07-13 15:57:41 -04:00
Jared Snider
c53620621b
Auth/PM-39905 - Restructure organization-invite into subfolders with barrel imports (#21642)
* PM-39905 - Restructure organization-invite into subfolders with barrel imports

Split the flat feature folder into nested subfolders. Services get the
abstraction at the top with a nested implementations/ folder for the
default impl, its spec, and the state file. Models live in their own
subfolder. The state file also picks up the .state.ts naming convention.

External consumers now import through the root barrel per the auth
CLAUDE.md convention rather than deep-importing individual files.

Piggy-backed rename: OrganizationInviteService.getInvitePolicies ->
getOrgPoliciesForInvite. Mirrors getMasterPasswordPolicyOptionsForInvite
and is clearer about what the method returns.

* PM-39905 - Update organization-invite-flows doc for restructured paths + rename

Refresh the companion design doc to match this PR's changes:

- Source-file links point at the new subfolder locations (models/,
  services/implementations/).
- getInvitePolicies references updated to getOrgPoliciesForInvite.

* PM-39905 - Expand organization-invite-flows doc with Key Connector SSO path

Add a third SSO subsection covering Key Connector JIT-provisioned users, plus
the corresponding member-decryption-option bullet under "The two acceptance
models". Rename "Why two cleanup points" -> "Why three cleanup points".

Also correct the MP command name to FinishSsoJitProvisionMasterPasswordCommand
(the prior SetInitialMasterPasswordCommand was renamed server-side and is now
marked [Obsolete]).

Notes the latent divergence in the KC path: neither the base component nor
the web override calls clearOrganizationInvite(), and fullSync doesn't touch
ORGANIZATION_INVITE_DISK, so the stashed invite persists on disk after
acceptance. Self-heals via subsequent overwrite or the email-mismatch guard.

---------

Co-authored-by: Patrick-Pimentel-Bitwarden <ppimentel@bitwarden.com>
2026-07-13 12:18:36 -04:00
John Harrington
58ee3edf55
[PM-37944] Differentiate Send events according to domain (#20787) 2026-07-13 07:24:13 -07:00
Addison Beck
7882bedb3e
feat(platform): introduce GovModeService for FedRAMP region gating [PM-38020] (#21366)
GovModeService is a shared Platform service that downstream teams consume to
gate FedRAMP-specific behavior.

The MVP implementation infers the gov-mode signal from the client-side Region
(true when `env.getRegion() === Region.Gov`). PM-36520 will replace the
implementation with a server-backed check while keeping this contract stable.

The service exposes two Observable surfaces: `globalIsGovMode$` (pre-login) and
`isGovMode$(userId)` (when a UserId is in scope). Consumers needing a Promise
snapshot bridge with `firstValueFrom` at the call-site -- the synthesis memory
A5086F94 captured the decision to omit Promise overloads from the service
surface.

Registered in all four app bootstraps: Angular DI (jslib-services.module),
browser background, CLI service-container, and desktop main. Unit tests cover
all four regions (Gov, US, EU, SelfHosted) for both API surfaces.
2026-07-10 11:57:11 -04:00
adudek-bw
474e3eb2b7
[PM-38392] Route password-protected Send saves through the SDK (#21725)
* [PM-38392] Route password-protected Send saves through the SDK

The SDK now exposes a `hashedPassword` SendAuthType variant (PM-38391,
sdk-internal #1197, present in the pinned 0.2.0-main.872) that forwards the
client-derived keyB64 verbatim without re-applying PBKDF2. Drop the temporary
workaround that routed password-protected saves to the legacy SendApiService.

- buildSendAuth: add AuthType.Password case returning
  { type: "hashedPassword", keyB64: sendView.password }, guarded against a
  missing derived key. keyB64 is a proof-of-knowledge and is never logged.
- Remove the password-protected save guards from SendApiServiceSelector and
  SendSdkApiService; the new-file-send fallback is unchanged.
- Update the now-stale workaround doc comments.
- Tests: flip selector password create/edit assertions to SDK routing; add
  send-sdk-api.service.spec.ts covering the hashedPassword output, the
  null-key guard, the none variant, and the new-file-send guard.

* [PM-38392] Use SDK high-level password auth for password-protected sends

The prior approach forwarded the client's pre-derived keyB64 to the SDK via
the hashedPassword variant. That is broken for creates: the SDK's create
generates its own send key, so a keyB64 derived over the client's (discarded)
key yields a password the user can never satisfy (verified end-to-end: correct
password rejected on receive). A maintainer also asked to move clients onto the
higher-level password API rather than the low-level hashed variant
(sdk-internal#1197).

Route password-protected sends through the SDK's plaintext `password` auth
variant so the SDK derives the proof-of-knowledge over the key it uses,
keeping password and key consistent by construction:

- Thread an optional plaintext password through SendApiService.save (abstraction
  + selector + legacy [ignored] + SDK impl) from the four callers that hold it
  at the encrypt() call (CLI create/edit, send-ui form service, angular
  add-edit).
- buildSendAuth: emit { type: "password", password } when a plaintext is present
  (create / password-change); emit { type: "hashedPassword", keyB64 } only for
  preserve-on-edit, where the SDK reuses the existing send key so the stored
  keyB64 stays valid. The existing keyB64 is recovered from stored state via
  getFromState (the freshly-encrypted Send carries none on a preserving edit).
- Plaintext password and keyB64 are Protected Data; never logged.

Verified: password create via SDK -> receive with correct password decrypts,
wrong password rejected. Unit tests cover all four buildSendAuth cases.

* [PM-38392] Only recover existing send password for password-protected edits

Address review S1: the existing-keyB64 recovery via getFromState fired on
every non-create save, including name-only edits of None/Email sends, whose
result buildSendAuth then ignores. Gate the state read on
send.authType === AuthType.Password so it only runs when the preserve-on-edit
branch can actually use it.

* Update apps/cli/src/tools/send/commands/create.command.ts

Co-authored-by: John Harrington <84741727+harr1424@users.noreply.github.com>

* Update apps/cli/src/tools/send/commands/edit.command.ts

Co-authored-by: John Harrington <84741727+harr1424@users.noreply.github.com>

---------

Co-authored-by: John Harrington <84741727+harr1424@users.noreply.github.com>
2026-07-10 09:30:18 -04:00
Todd Martin
13eb509791
fix(self-hosted): [PM-39218] Use global environment for self-hosted env dialog and SSO URL
* Use global environment for self-hosted env dialog and SSO URL

Both flows run before a user is authenticated, so they must read from
the global environment; the user-scoped environment isn't populated
until login completes.

* Moved SSO callback to Auth ownership.
2026-07-09 16:29:35 -04:00
rr-bw
3688d2224f
[PM-35600] Update Password Request Models (Key Management) (#20665)
* update KdfRequest

* update PasswordRequest

* update changePassword() to use new PasswordRequest format

* update test setup

* update KdfRequest to include current/old masterPasswordHash

* update PasswordRequest to require current hash

* remove unused postAccountKdf() from ApiService

* rename to ChangeKdfRequest

* move ChangeKdfRequest to key-management/kdf/models/

* remove extra blank line

* update postPassword test to use new PasswordRequest format

* Update libs/common/src/key-management/kdf/models/change-kdf.request.ts

Co-authored-by: Maciej Zieniuk <167752252+mzieniukbw@users.noreply.github.com>

---------

Co-authored-by: Maciej Zieniuk <167752252+mzieniukbw@users.noreply.github.com>
Co-authored-by: Patrick-Pimentel-Bitwarden <ppimentel@bitwarden.com>
Co-authored-by: Dave <3836813+enmande@users.noreply.github.com>
2026-07-09 20:16:55 +00:00
Addison Beck
97ea9c7dcd
feat: add Region.Gov to available environments (#21211)
* feat(platform): add Region.Gov and Gov entry to PRODUCTION_REGIONS [PM-38018]

Adds Gov: "Gov" to the Region const object (between EU and SelfHosted)
and appends a third entry to PRODUCTION_REGIONS alongside US and EU.
The CloudRegion type (Exclude<Region, "Self-hosted">) automatically
includes Gov.

The Gov entry uses bitwarden-gov.com as its domain with all subdomain
URLs explicit. The send URL is stored bare (no trailing /#/) per the
convention established by PM-2588 — getSendUrl() appends the hash at
read time.

Region.Gov is the foundational constant for the GovMode / FedRAMP cloud
environment work tracked under PM-35087. Flag-gated visibility in the
environment selector is introduced separately in PM-38019 via
AvailableRegionsService; this commit deliberately makes the region
unconditionally returned by EnvironmentService.availableRegions().

DEFAULT_MARKETING_EMAILS_PREF_BY_REGION in registration-start.component
gets a Gov: false entry to satisfy the Record<Region, boolean> type.

* feat: introduce AvailableRegionsService for runtime region filtering

Creates AvailableRegionsService and DefaultAvailableRegionsService in
libs/common/src/platform/. The service exposes availableRegions$, a
flag-gated Observable that wraps EnvironmentService.availableRegions()
and filters Region.Gov by the FedRampGovRegion feature flag. US and EU
are always present regardless of flag state.

EnvironmentService cannot hold this filter directly: ConfigService
depends on EnvironmentService to resolve API URLs, so wiring the
feature-flag check into EnvironmentService would create a circular
dependency. AvailableRegionsService sits above both and composes them.

The implementation uses startWith(false) so Gov is hidden until the flag
value arrives from the server. This avoids a flicker where Gov would
briefly appear during cold start before the flag resolves.

Registered in the renderer Angular DI module (covers web and desktop
renderer), the browser background script, and the CLI service container.
apps/desktop/src/main.ts intentionally excludes the service: no
main-process consumer needs a flag-gated region list, and desktop main
does not construct ConfigService, so registering here would require a
feature-flag shim to satisfy a constructor dependency with no consumer.

The accompanying spec covers four behaviors: Gov inclusion when the flag
is true, Gov exclusion when the flag is false, Gov exclusion on the
initial startWith(false) seed before the flag emits, and the US/EU
invariant across both flag states. Asserts inspect the last emission of
a take(2) window rather than firstValueFrom because the startWith(false)
seed always emits first regardless of the flag value, so asserting the
first emission would falsely pass for the wrong reason.

The selector-component migration that consumes this service lands in
a follow-up commit on the same branch. Shipping both in one PR closes
the release window where Gov could leak into the environment selector
because unmigrated selectors read EnvironmentService.availableRegions()
directly and never observe the flag.

* refactor(auth): migrate environment selector components to AvailableRegionsService

Migrates the three environment-selector components from
EnvironmentService.availableRegions() to AvailableRegionsService.
availableRegions$. Each component receives AvailableRegionsService via
constructor injection and replaces the synchronous availableRegions
array with the flag-gated Observable. All three templates switch from
synchronous-field iteration to the | async pipe.

The web selector resolves currentRegion synchronously via
EnvironmentService.availableRegions() rather than the flag-gated stream,
because origin validation must succeed regardless of flag state. The dropdown
options continue to use availableRegions$ | async. This pattern matches the
JSDoc guidance on AvailableRegionsService: the service is the UI display
source, while EnvironmentService.availableRegions() is the source for URL
resolution, origin validation, and stored-region rehydration.

The shared and registration components use combineLatest to pair the
flag-gated region list with the active-environment stream so
selectedRegion$ stays in sync with changes to either source. The
registration component's Environment import becomes unused after
combineLatest infers the type that the previous map(env: Environment)
annotation required, and is removed to satisfy ESLint's
@typescript-eslint/no-unused-vars rule.

Shipping this migration in the same PR as the AvailableRegionsService
introduction closes the release window where Gov could leak into any
client's environment selector. Unmigrated selectors read
EnvironmentService.availableRegions() directly and would surface Gov
unconditionally; migrating them in this PR makes the FedRampGovRegion
flag the single gate for selector visibility.

These three components live in Auth-owned paths
(libs/angular/src/auth/, apps/web/src/app/components/, and
libs/auth/src/angular/registration/). Auth is a required reviewer on
this PR.

* fix(auth): provide AvailableRegionsService mock in stories

* fix(auth): align env-picker dropdown icon vertically

The trigger's <bit-icon bwi-angle-down> renders inline-block with
vertical-align: baseline, which hangs below the baseline of the
line box. Combined with bitLink's tw-leading-none, this clipped
the text descenders of the "Accessing:" label on desktop and
browser login footers.

Adding tw-align-middle to the icon restores normal line-box
metrics and eliminates the clipping.

Root cause latent since PR #18816 migrated the trigger icon from
<i class="bwi"> to <bit-icon>. Web is unaffected because its
trigger uses an inline-flex <a bitLink>. This fix is
flag-independent — FedRampGovRegion only gates dropdown contents,
not the trigger label.

Refs: PM-39401

* Revert "fix(auth): align env-picker dropdown icon vertically"

This reverts commit 2d51461be9.

---------

Co-authored-by: kmancusi0105 <kmancusi@bitwarden.com>
2026-07-09 15:17:26 -04:00
Bernd Schoolmann
a8f8605a69
[PM-39259] Migrate vault export and generator to SDK random number client (#21708)
* [PM-39259] Migrate tools to SDK randomness

* fix(tests): Fix tests for sdk randomizer
2026-07-09 07:38:31 -07:00
Brandon Treston
7d1c11ee93
[PM-35796] Use SDK bindings for invite link generation (#21004)
* clean up types, fix tests

* update types

* update to SDK types

* refactor to use SDK client implementation

* bump SDK version

* refresh lock file

* Revert "refresh lock file"

This reverts commit bc32946128.

* update models for milestone 3 future work

* clean up

* more clean up

* add supportConfirmation to refresh, update doc

* clean up

* remove supportsConfirmation from update code path, rename

* fix test failures

* fix story
2026-07-09 09:27:34 -04:00
Bernd Schoolmann
7fd44eb77d
[PM-39259] Migrate key-management key-generation to SDK (#21707) 2026-07-09 17:25:06 +09:00
luo jiyin
5236f110e3
[PM-39177] fix(libs): correct various typos in shared libraries and documentation (#21320)
* fix(libs): correct various typos in shared libraries and documentation

Part of #21319 — batch typo corrections with typos-cli.

* fix(anon-layout,master-password,container): revert incorrect typo fixes flagged in review

* fix(utils): revert regex pattern changes flagged in review

* fix(fido2-authenticator): revert base64 seed string incorrectly changed by typo checker

* fix(master-password): revert test string incorrectly changed by typo checker

* fix(master-password): restore iif() usage, not a typo

* fix(anonymous-hub,protonpass): revert hub event name, fix Floor typo

* fix(protonpass): sync twitter handle typo fix in test data
2026-07-07 15:27:55 +00:00
Jared
7e52f22e66
[PM-35812] Remove feature flag (#21567)
* Remove ConfigService references from MainBackground, jslib-services.module, and DefaultAutomaticUserConfirmationService. Update related tests to reflect these changes.

* Add OrganizationService mock to SimpleTogglePolicyComponent tests
2026-06-30 15:24:20 -04:00
Bernd Schoolmann
4b6b42cd83
Enable no relative imports rule (#21515) 2026-06-26 09:20:10 -05:00
Jared Snider
c2f8681146
PM-21301 - Move SelfHostedEnvConfigDialog out of libs/auth (#21268)
Relocate the self-hosted environment configuration dialog from
libs/auth/src/angular/self-hosted-env-config-dialog/ to
libs/angular/src/auth/self-hosted-env-config-dialog/, with a leaf
barrel matching the destination's convention.

First slice in an effort to decompose libs/auth and reduce the
circular dependencies that motivated keeping new code out of it.
Unblocks a subsequent move of the registration subtree, which
imports this dialog from registration-env-selector.

- New leaf barrel at the destination so consumers import the
  feature, not the component file.
- Source barrel entry in libs/auth/src/angular/index.ts removed.
- environment-selector.component.ts switched to a same-lib relative
  import; its stale no-restricted-imports suppression was cleared
  by lint:fix because the import no longer crosses libs.
- registration-env-selector.component.ts switched to a cross-lib
  @bitwarden/angular/auth subpath import. This becomes a same-lib
  relative once registration itself moves in the follow-up PR.
2026-06-25 11:59:11 -04:00
Eli Grubb
25dffc9ff9
[PM-24223] Add feature flagged support for password v2 registration (#20782)
Add feature flagged support for master password encryption v2 registration
2026-06-25 08:47:10 -06:00
Jared McCannon
291d5527e2
[PM-38904] - Managed to Claimed Rename (#21430)
* renamed from deprecated properties to replacements

* added alias to old property in case pulling from disk
2026-06-24 09:30:06 -05:00
Bernd Schoolmann
2592ccf7ad
[PM-37875] Automatic V2 Upgrade Migration (#20831) 2026-06-23 17:47:47 +09:00
Bernd Schoolmann
53db9ffb67
[PM-39182] Migrate to relative imports - @bitwarden/team-billing-dev (#21325) 2026-06-22 22:32:47 +09:00
Bernd Schoolmann
830d160006
[PM-39182] Migrate to relative imports - @bitwarden/team-auth-dev (#21330)
* [PM-39182]  @bitwarden/team-auth-dev

* Eslint
2026-06-22 22:31:34 +09:00
Bernd Schoolmann
9e73ef9b48
[PM-39182] Migrate to relative imports - @bitwarden/team-key-management-dev (#21333)
* [PM-39182]  @bitwarden/team-key-management-dev

* Set to warn
2026-06-22 11:39:50 +02:00
Jared Snider
26250f929a
Auth/PM-35783 - Fix Org Invite Policy State Pollution and State Clearing Issue (#21218)
* PM-35783 - Add invite MP-options primitive to OrganizationInviteService

Adds `getMasterPasswordPolicyOptionsForInvite(invite)` to the
OrganizationInviteService abstraction and default implementation. Composes the
existing `getInvitePolicies` (cached fetch) with `policyService.combinePoliciesIntoMasterPasswordPolicyOptions`
to return the MP requirements for an invite's organization.

Adds a TODO at `WebRegistrationFinishService.getMasterPasswordPolicyOptsFromOrgInvite`
flagging future consolidation onto this new primitive once invite acceptance
becomes cross-client.

* PM-35783 - Add MP-policy resolution to ChangePasswordService

Adds `resolveMasterPasswordPolicyOptions(userId)` to the ChangePasswordService
abstraction and default implementation. Combines the user's joined-org policies
(synced state via `policyService.masterPasswordPolicyOptions$`) with any
in-flight invite's policies (via `OrganizationInviteService.getMasterPasswordPolicyOptionsForInvite`)
into the strictest applicable MP requirements.

Plumbs the new `PolicyService` + `OrganizationInviteService` constructor deps
through DefaultChangePasswordService, WebChangePasswordService,
ExtensionChangePasswordService, and the three DI modules.

No consumer yet - the change-password component still uses its inline helpers.

* PM-35783 - Delegate MP-policy resolution from ChangePasswordComponent

Replaces the inline `resolveMasterPasswordPolicyOptions` + `getInviteMasterPasswordPolicyOptions`
helpers with a single call to `changePasswordService.resolveMasterPasswordPolicyOptions(userId)`.
Domain logic now lives in the service (tested) rather than the component.

Drops `PolicyService` and `OrganizationInvite` imports + constructor injection
that are no longer needed; `OrganizationInviteService` stays - it is still used
by `logOut()` to clear the stash.

* PM-35783 - Stop writing invite policies to global policy state on login

Removes `setPoliciesIntoState` and its call site. The previous behavior wrote
the invited org's policies into `policyService` + `newPolicyService` global
state as a workaround for `/change-password` only reading from state - which
overwrote the user's actual joined-org policies (populated by the preceding
full sync) and caused the invited org's policies to leak into the vault UI
when the accept failed (e.g. Single Org policy enforcement after a
server-rejected accept).

The redirect decision still happens here off the in-memory
`orgPoliciesFromInvite.enforcedPasswordPolicyOptions`. The change-password
screen now resolves its requirements via
`ChangePasswordService.resolveMasterPasswordPolicyOptions`, which composes the
user's joined-org policies from synced state with the stashed invite's policies.

* PM-35783 - Clear stashed invite on org-invite accept failure

Adds an optional `onError` hook to `AcceptFlowConfig`, invoked from
`AcceptFlowService.handleError` before the toast + redirect (fires on both
thrown handler and invalid-link paths).

`AcceptOrganizationComponent` wires this to
`organizationInviteService.clearOrganizationInvite()`. Every server-side accept
rejection (expired, revoked, already-accepted, policy violations) is a
permanent failure, so retaining the stash would let its policies bleed into
later voluntary change-password attempts via the new
`resolveMasterPasswordPolicyOptions` fallback path.

`AcceptFlowService` stays generic over `TInvite` - the org-invite-specific
cleanup is wired by the component, not the service.
2026-06-18 12:51:10 -04:00
Bernd Schoolmann
4ef127355d
[PM-39182] Migrate to relative imports - @bitwarden/team-vault-dev (#21331) 2026-06-18 15:10:16 +00:00
Bernd Schoolmann
298972203f
[PM-39182] Migrate to relative imports - @bitwarden/team-tools-dev 2026-06-18 02:08:23 +00:00
rr-bw
9fc071c65e
fix(extension-scrollbar): Auth [PM-32445] Extension Scrollbar Fix (#20478)
Makes design adjustments so that a scrollbar does not appear on particular Extension pages:
- /login
- /login-with-passkey
- /signup
- /lock
2026-06-17 15:17:36 -07:00
cyprain-okeke
cd2bed4401
[PM 35229](clients) [Browser/Desktop] Stripe Checkout from upgrade dialog (#20592)
* Add changes for stripe checkout

* fix the type checkimg error

* Fix premium upgrade dialog storybook providers

* [PM-38393] bypass cloud check for stripe checkout for qa (#21212)

* feat: add DebugDisableSelfHostPremiumCheck feature flag

* feat: bypass self-host check for premium checkout behind QA flag

* test: pin self-host fallback test to bypass flag off

* feat: bypass self-host check for subscription pricing behind QA flag

Gate the subscription-pricing API calls on DebugDisableSelfHostPremiumCheck
in addition to the cloud check, so a self-hosted-region client can fetch and
display prices in the premium checkout dialog when the QA flag is enabled.

---------

Co-authored-by: Kyle Denney <4227399+kdenney@users.noreply.github.com>
2026-06-17 16:36:47 +01:00
Jared Snider
8baa8902ab
Auth/PM-38298 - Org Invite Acceptance Refactor (#21011)
* PM-38298 - Add AcceptFlowService to libs/angular

Extracts the shared param-check → auth-status → handler-dispatch →
error-handling shell from BaseAcceptComponent into a reusable, generic
Angular orchestration service. Pure addition with no consumers yet.
The component migration off BaseAcceptComponent lands in a later commit.

* PM-38298 - Relocate organization-invite to libs/common feature folder

Renames libs/common/src/auth/services/organization-invite/ to
libs/common/src/auth/organization-invite/, matching the feature-folder
convention used by password-prelogin, send-access, and two-factor.

Rewrites the ~14 repo-wide import sites in lockstep and adds an index.ts
barrel. Pure rename - no logic changes. Sets up a cleaner home for the
merged service that follows in the next commit.

* PM-38298 - Merge AcceptOrganizationInviteService into DefaultOrganizationInviteService

Eliminates the artificial state/orchestration split: the apps/web
AcceptOrganizationInviteService is absorbed into the libs/common
DefaultOrganizationInviteService, which now owns state persistence,
validate-and-accept orchestration, and policy fetching.

Key changes:
- Extends the OrganizationInviteService abstract class with
  validateAndAcceptInvite and getInvitePolicies.
- Folds the WebOrganizationInviteService state backing (GlobalStateProvider
  + ORGANIZATION_INVITE KeyDefinition) into the merged impl.
- Promotes the orchestration's private getPolicies to public
  getInvitePolicies, keyed by invite token, and adds full cache
  invalidation on setOrganizationInvitation / clearOrganizationInvitation
  so the now-app-scoped instance never serves stale entries.
- Updates the OrganizationInviteService DI registration in
  jslib-services.module.ts with the impl's expanded dependency list.
- Removes the apps/web WebOrganizationInviteService provider override and
  deletes the file - the libs/common impl now serves all clients.
- Adds eslint suppressions for the admin-console and key-management
  imports per the existing libs/common decomposition pattern.
- Adds a libs/common spec covering state, orchestration, and cache
  invariants.

AcceptOrganizationInviteService in apps/web still exists at this point;
component migration off it lands in the next commit.

* PM-38298 - Migrate AcceptOrganizationComponent off BaseAcceptComponent

Drops the BaseAcceptComponent inheritance pattern for AcceptOrganization:
the component now consumes AcceptFlowService (libs/angular) for the
orchestration shell and OrganizationInviteService (libs/common) for
invite validation and acceptance, with the same authedHandler /
unauthedHandler / "Expired token." error-mapping semantics it had as a
BaseAcceptComponent subclass.

Also:
- Converts AcceptOrganizationComponent to standalone with explicit
  IconModule and I18nPipe imports for the template's bit-icon and i18n
  pipe usage.
- Deletes AcceptOrganizationInviteService and its spec - the
  orchestration logic now lives in the merged libs/common service.
- Deletes accept-organization.module.ts (no longer needed once the
  component is standalone and its only provider, the legacy service,
  is removed) and drops it from auth.module.ts.

BaseAcceptComponent and its five other subclasses are out of scope; they
keep extending the base class.

* PM-38298 - Consolidate org-invite policy-fetch consumers

Routes the duplicated "fetch org policies via invite token" pattern
through OrganizationInviteService.getInvitePolicies(invite) so callers
share one cached implementation instead of each calling
policyApiService.getPoliciesByToken directly.

Migrates four call sites:
- web-login-component.service.ts (drops the now-unused
  PolicyApiServiceAbstraction injection; inline email-mismatch handling
  stays).
- web-registration-finish.service.ts (drops PolicyApiServiceAbstraction
  and LogService injections; error logging moves into the merged
  service).
- complete-trial-initiation.component.ts (drops policyApiService and
  logService injections).
- core.module.ts deps arrays updated to match the trimmed constructors;
  the now-orphaned PolicyApiServiceAbstraction import is removed.

Also fixes web-login-decryption-options.service.spec.ts, which had been
importing AcceptOrganizationInviteService directly as a mock target -
swapped to OrganizationInviteService to match the production wiring and
unblock the deletion in the previous commit.

Spec updates mirror the production changes: existing it() cases that
asserted against getPoliciesByToken now assert against getInvitePolicies.

* PM-38298 - Make OrganizationInvite enforce its own contract

Replaces the loose, all-optional OrganizationInvite shape with one that
matches the server contract emitted by OrganizationUserInvitedViewModel.Url:
seven fields are always present, only orgSsoIdentifier is conditional
(server emits it only when the org has SSO + the SSO-required policy on).

Key changes:
- All seven always-present fields become non-optional. orgSsoIdentifier
  stays optional.
- Adds a real constructor taking a typed data object, so partial
  construction is a compile error - the previous Object.assign + empty
  ctor pattern silently allowed test fixtures to omit fields.
- Adds an OrganizationInviteUrlParams interface documenting the URL
  query-string shape the server emits, so the contract is captured in
  code (no more spelunking the C# server file). Sets up future
  open-invite-link and browser-extension URL parsers to share the type.
- Adds OrganizationInvite.fromUrlParams static factory that validates +
  narrows the untyped Angular Params bag into the shape and returns
  null on any missing/invalid field. Replaces the private fromParams
  method that previously lived on AcceptOrganizationComponent - parsing
  now lives with the domain class, where the next two consumers
  (open-invite-link, browser-extension invite acceptance) can reuse it.
- fromJSON rebuilt to use the constructor.

Consumer cleanup made possible by the tightened type:
- complete-trial-initiation.component.ts drops the defensive
  invite.organizationId / token / email / organizationUserId truthiness
  checks. The type guarantees these are present whenever invite != null.

Test fixtures across web-registration-finish.service.spec.ts,
web-login-component.service.spec.ts, and the libs/common spec helper
all updated to construct via the new ctor. Adds a new
organization-invite.spec.ts covering the ctor, fromUrlParams (happy
path, every required-param-missing case, GUID validation, boolean
coercion, optional passthrough), and fromJSON.

* PM-38298 - Remove @ts-strict-ignore from invite-related files

Three files in the org-invite refactor footprint had carry-over
@ts-strict-ignore pragmas. tsc-strict now reports them clean - drops
the pragma + FIXME comment from each:

- libs/common/src/auth/organization-invite/default-organization-invite.service.spec.ts
- apps/web/src/app/auth/core/services/registration/web-registration-finish.service.spec.ts
- apps/web/src/app/auth/organization-invite/accept-organization.component.ts

The merged DefaultOrganizationInviteService itself still carries the
pragma - removing it there requires in-file null guards for
activeAccount$ and userKey$, plus EncString.encryptedString handling,
which is a separate follow-up.

* PM-38298 - Drop dead null guards in OrganizationInviteService

After tightening OrganizationInvite to enforce required fields at its
constructor and at every typed callsite, the runtime
`if (invite == null) throw` guards in setOrganizationInvitation and
validateAndAcceptInvite became unreachable code - the abstract class
signature already rejects null at compile time, and every consumer
either constructs an invite via the typed constructor / factory, or
narrows with `if (invite != null)` before calling.

Removes:
- The two null-throw guards in DefaultOrganizationInviteService.
- The corresponding @throws JSDoc on the abstract class.
- The two "throws when invite is null" tests, which were verifying
  behavior the type system now prevents (and required passing `null`
  in places the signature no longer accepts it).

No behavior change for typed callsites: the only way to reach the
removed code paths was to defeat the type system with `as any`, which
is already undefined-behavior territory.

* PM-38298 - Make DefaultOrganizationInviteService type-safe

Switch getInvitePolicies to return undefined instead of null (per the
strict-mode ADR), plumb the user ID through the accept path so we no
longer have to read it from a nullable observable, and add defensive
guards around encryption outputs that the request constructors require.
Drops the now-unused AccountService dependency.

* PM-38298 - Address code review findings on org-invite refactor

Two small follow-ups from the post-refactor review:

- Document the trust-boundary asymmetry between OrganizationInvite's two
  static factories. fromUrlParams validates external URL input;
  fromJSON trusts persisted state because the only write path goes
  through the typed constructor, which already enforces required fields.
  A short JSDoc on fromJSON makes the choice explicit so readers don't
  flag the missing validation as an oversight.

- Restore the end-state assertions on two validateAndAcceptInvite cases
  that lost coverage when the apps/web spec was ported to libs/common:
  the initOrganization=true path and the no-MP-policy accept path both
  now verify the invite is cleared from state after acceptance. Brings
  them in line with the other "happy-path accept" cases that already
  check `expect(stored).toBeNull()`.

* PM-38298 - Fill org-invite test gaps

Cover the type-safety guards added in c475c541be and a few cache/edge
cases that were not exercised:

- DefaultOrganizationInviteService: throws when any encrypted output is
  null in acceptAndInitOrganization (3 cases); throws when org keys
  fetch returns null, user key is null, or the encapsulated user key is
  null in the reset-password enrollment path (3 cases); getInvitePolicies
  scopes its cache by invite token and does not cache null API results.
- AcceptFlowService: AuthenticationStatus.Locked routes to authedHandler;
  non-Error throws fall through to the full failed-message path; null
  queryParams is treated as a missing-param error.

* PM-38298 - Skip stale-invite clear when no invite is stored

* PM-38298 - Refactor AcceptFlowService to typed-parse shape

Move URL parsing into AcceptFlowService via a required parse callback
and dispatch the parsed result as a typed TInvite to both handlers.
Symmetric try/catch around authedHandler and unauthedHandler so error
handling no longer asymmetrically depends on which branch the user
lands in.

AcceptOrganizationComponent loses its requiredParameters field, its
handleInvalidInvite method, and both inline 'if (invite === null)'
guards; OrganizationInvite.fromUrlParams (validates presence + GUID
format) is now the single source of truth for invalid-link detection,
strictly stronger than the prior presence-only string-array check.

* PM-38298 - Add JSDoc to AcceptFlowService

* PM-38298 - Add JSDoc class headers to org-invite contracts

* PM-38298 - Remove dead org-invite policy lookup from trial initiation

* PM-38298 - Document policy cache in OrganizationInviteService

* PM-38298 - Rename OrganizationInvitation methods to OrganizationInvite

* PM-38298 - Document organization invite acceptance flows

* PM-38298 - Flag MP-policy logout branch for reachability investigation

* PM-38298 - Document MP-policy logout branch reachability

Replace the reachability TODO on validateAndAcceptInvite's MP-policy
logout branch with an inline explanation of the trigger (authed user
pastes the accept-invite URL into a signed-in session). Extend the
flow docs with the same scenario and align the SSO acceptance bullets
with the application's "member decryption option" terminology, plus a
scope note on the global single-slot stash.

* PM-38298 - Clarify init-organization invite scenario in flows doc

* PM-39073 - Surface ErrorResponse messages from accept flow

Recognize ErrorResponse alongside Error in AcceptFlowService's catch block
so server-side messages reach the toast instead of being dropped. ErrorResponse
extends BaseResponse, not Error, so the prior `instanceof Error` guard lost
the API message and fell back to the generic invite-failed string.
2026-06-16 11:35:10 -04:00
Jared Snider
36805f689f
Auth/Add CLAUDE.md files to angular/src/auth and common/src/auth on file organization + barrel files (#21283)
* Add CLAUDE.md files to angular/src/auth and common/src/auth

* Remove unnecessary reference
2026-06-15 21:35:10 +00:00
Thomas Rittson
0e9b1b2cfd
Fix malformed policy sync response parsing (#21189) 2026-06-11 09:47:03 -04:00
Bernd Schoolmann
5ddbf986cd
[PM-31059] Implement SDK managed PIN unlock (#20395)
* Implement state bridge support

* Implement SDK managed PIN unlock

* Update package.lock

* Update sdk

* Prettier

* Fix test mock

* Cleanup

* Cleanup

* Fix name

* Add timeout

* Fix type issue

* prettier

* Remove unecessary try catch

* Add comment

* Cleanup

* Delete spec file

* Fix missing userid

* Cleanup

* Fix DI

* Fix build errors

* Fix tests

* Fix desktop and browser builds

* Fix spec

* Remove unused vars

* Fix eslint

* Prettier and replace pin polling

* Cleanup

* Clean up unlock service

* Undo change to spec ts

* Rename unlock decrypted key

* Remove unused var

* Remove unused import

* Prettier

* Merge

* Remove unused import

* Clean up comment

* Await with pin settings client calls

* Make sdk service emit locked instance

* Fix build

* Remove unused import

* Fix tests and move assertions to annotation

* Add unit tests

* Prettier

* Fix eslint

* Initialize state and flags for locked client

* Prettier

* Cleanup

* Remove unused import
2026-06-10 09:19:48 -05:00
Nick Krantz
c9e1d9c5c0
Fix shareReplay memory leaks in canCloneCipher$ and hasActiveBadges$ (#21087) 2026-06-10 08:25:54 -05:00
Thomas Avery
dfd6a8f100
[PM-31054] Add V2UpgradeToken handling to sync (#20641)
* Add state service for V2UpgradeToken

* Update clear to not write to disk every call

* Fix unit test

* Add V2UpgradeToken handling to sync

* Add passing V2UpgradeToken to SDK unlocks

* Fix new DefaultUnlockService in main background

---------

Co-authored-by: Bernd Schoolmann <mail@quexten.com>
2026-06-10 16:52:24 +09:00
Jordan Aasen
da01c56f14
[PM-37173] - Add churn-offer dialog to organization cancel flow (#20866)
* Add churn-offer dialog to organization cancel flow

* updates to dialog styling

* style updates

* consolidate tw class

* small content fixes

* fix icon. update endpoints
2026-06-09 16:25:29 -07:00
Bernd Schoolmann
25f3232bb9
[Shared Unlock] [PM-35083] Shared Unlock for Web, Browser, Desktop (#19698)
* Add shared unlock TS services

* Add newline

* Small cleanup

* Fix type error

* Fix type issue

* Eslint and prettier fixes

* Cleanup

* Prevent eslint error

* Prettier

* Add tests

* Cleanup

* Fix type issue

* Cleanup

* Implement basic version of flagged biometrics ipc over sdk ipc

* Move code

* Noop ipc service

* Clean up unlock service

* Undo change to spec ts

* Rename unlock decrypted key

* Remove unused var

* Remove unused import

* Prettier

* Fix eslint

* Ensure connected

* Undo changes to electron key service

* Newline

* Newline

* Remove biometrics.ts

* Fix

* Shared unlock

* Cleanup

* Cleanup

* Use unlock service for unlocking on shared unlock

* Cleanup comment

* Cleanup

* Prettier and eslint cleanup

* Fix browser build

* Prettier

* Fix test

* Eslint

* Fix types

* Remove log

* Remove service

* Remove unused file

* Cleanup

* Fix DI

* Set unlock service on biometric service

* Address feedback

* Await floating promise

* Prettier

* Await floating promise

* Remove duplicate i18n key

* Apply fixes

* Run init in background

* Cleanup

* Default the feature flags to false

* Cleanup

* Fix DI

* Fix DI

* Remove duplicate ipc init

* Remove duplicate DI

* Address feedback

* Remove unused services from DI

* Fix init of service

* Convert driver to class

* Relative imports

* Relative imports

* Remove unused code

* Non null assertion

* Use @if

* Init sdk only once

* Convert shared unlock description key to getter

* Remove unecessary checks

* Gate biometrics based on either biometrics or shared unlock

* Cleanup

* Fix test

* Prettier

* Cleanup

* Use update allow sharing unlock state function

* Remove warning

* Remove discovery handler and background task

* Fix build

* Remove unused i18n key

* Remove unused services
2026-06-09 09:12:51 +09:00
adudek-bw
f9c569379c
Add new SendApiServer that uses the SDK (#20170)
* Add new SendApiServer that uses the SDK
2026-06-02 14:19:45 -04:00
Bernd Schoolmann
d4acb9e67e
[PM-37875] Split out crypto verification UI (#20856)
* Extract user crypto dialog to ui module

* Fix build

* Prettier

* Fix DI injection
2026-06-02 08:13:39 -05:00
Thomas Rittson
007b5d9335
[PM-34157] Wire up SDK to NewPolicyService (#20377)
* Add shim in PolicyService to NewPolicyService
* Wire up NewPoilcyService to SDK
* Use SDK enum
2026-05-28 07:14:53 +10:00
Nick Krantz
500345d57f
[PM-37970] Fix vault list icons for Login and Identity with new item types flag (#20818)
* update cipher icons per the new items feature flag

* fix testing dependencies
2026-05-27 16:01:39 -05:00
Stephon Brown
283a0782c2
[PM-35228] Add Premium Status Changed Push Notification (#20498) 2026-05-27 14:32:17 -04:00
Jordan Aasen
97de2515db
[PM-35120] - Update user delete flows with org ownership (#20462)
* update delete account flows

* fix type error

* add account deletion service

* revert i18n key add to IN

* fixes to delete account dialog flow
2026-05-22 09:58:43 -07:00
Will Martin
d7d74825f8
[CL-1046] Add no-bit-dialog-wrapper lint rule (#20698)
* [CL-1046] Add no-bit-dialog-wrapper lint rule

Errors when <bit-dialog> or <bit-simple-dialog> appears inside any
parent HTML element. The dialog selector should be applied as an
attribute on the root element (e.g. <form bit-dialog>) so that the
form receives the dialog's height styling.

* Migrate admin console dialogs to new form pattern

Updates organization member, group, collection, provider, and domain verification dialogs to use <form bit-dialog> pattern following the component library updates.

* Migrate auth settings dialogs to new form pattern

Updates two-factor authentication, WebAuthn, and emergency access dialogs to use <form bit-dialog> pattern following the component library updates.

* Migrate Secrets Manager dialogs to new form pattern

Updates project, service account, access token, and secret dialogs to use <form bit-dialog> pattern following the component library updates.

* Migrate remaining dialogs to new form pattern

Applies the <form bit-dialog> / <form bit-simple-dialog> attribute selector
pattern to the rest of the codebase, satisfying the no-bit-dialog-wrapper
lint rule. 55 templates across auth, admin console, billing, vault,
key management, secrets manager, provider, dirt integrations, importer,
browser, and desktop apps.

* Migrate key rotation dialog to new form pattern
2026-05-20 09:47:14 -04:00
Nick Krantz
2a8e589f2f
[PM-37229] Add bwi-passport icon for passport cipher type (#20712)
* [PM-37229] Add bwi-passport icon and wire it to the passport cipher type

* Fix icons:build script to compile style.css and avoid duplicate SCSS keys

* [PM-37229] Update passport cipher icon tests to expect bwi-passport
2026-05-19 15:26:26 -05:00
Leslie Tilton
d25e043248
Add route providers to featureFlaggedRoute (#20235) 2026-05-18 12:31:24 -05:00
Jared
1b17557475
[PM-37521] Refactor password strength component for improved performance and to properly work (#20650)
* Refactor password strength component for improved performance and readability

- Introduced ChangeDetectorRef to optimize rendering in response to input changes.
- Consolidated visual update logic into a separate method for clarity.
- Enhanced handling of password strength calculations and visual feedback.
- Ensured real-time updates for password strength in the input-password component.

* Enhance password strength component's ngOnChanges method for better performance

- Updated ngOnChanges to debounce rendering only for email or name changes, avoiding unnecessary renders for password updates.
- Improved clarity of the method by explicitly handling password changes.

* Update tests for PasswordStrengthV2Component to include email change handling

- Modified ngOnChanges test cases to simulate email changes using SimpleChange.
- Ensured that password score emissions are correctly tested when email input is updated.
2026-05-15 12:04:45 -04:00
Bernd Schoolmann
ab941afa89
[PM-31061] Implement biometrics migration (#20506)
* Revert "Revert "[PM-31061] Implement biometrics migration (#20127)" (#20455)"

This reverts commit 7ddfddc695.

* Update sdk

* Clean up lock file

* Restore package lock

* Package lock

* Fix tests

* Remove unused mocks

* Cleanup

* Remove imports

* Revert changes to main.ts

* Deduplicate setting of key id

* Cleanup

* Prettier

* Update libs/common/src/key-management/encrypted-migrator/default-encrypted-migrator.spec.ts

Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com>

* Update apps/browser/src/key-management/biometrics/foreground-browser-biometrics.ts

Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com>

---------

Co-authored-by: Thomas Avery <43214426+Thomas-Avery@users.noreply.github.com>
2026-05-15 12:22:41 +09:00
Thomas Avery
28149b04ce
[PM-31054] Add state service for V2UpgradeToken (#20636)
* Add state service for V2UpgradeToken
2026-05-14 10:56:50 -05:00
Nick Krantz
9eb416200b
[PM-36877] Remove nudge from bank account cipher type (#20561) 2026-05-14 08:49:38 -05:00
Brandon Treston
947920ed8d
[PM-34405 | PM-34406] Invite url field (#20557)
* improve type safter for invite link, add allowed domains field, wire up local state

* clean up

* fix reactivity

* clean up

* wip

* fix 404 handling, remove redundant signal

* add shareReplay

* update tests

* fix tests

* fix template, state clearing, more guards, clean up

* clean up

* cache org link by ID

* clean up

* clean up

* fix copy

* clean up

* more clean up
2026-05-13 09:34:25 -04:00
Jackson Engstrom
d7a7bc3554
[PM-32019] Add diamond action chip to archive menu option in desktop (#20186) 2026-05-11 11:42:19 -07:00