Commit Graph

7320 Commits

Author SHA1 Message Date
sneakernuts
c073026973 SRE-4899 node 20 to 24 (#7685) 2026-05-20 13:04:34 -06:00
Jimmy Vo
8540c6f0c1 [PM-36678] Add custom user check (#7675) 2026-05-20 14:38:34 -04:00
Alex Morask
34d4b6b3f6 [PM-37068] feat: Add business plan cohort branch to UpcomingInvoiceHandler (#7678)
* [PM-37068] feat: Add business plan cohort branch to UpcomingInvoiceHandler

Wires the caller side of the Teams/Enterprise 2020 → current price
migration. AlignOrganizationSubscriptionConcernsAsync becomes a
ProductTier dispatcher; the new business branch loads the cohort
assignment, runs eligibility guards (assignment unscheduled, cohort
active, org PlanType matches cohort source), and invokes PM-37064's
ScheduleBusinessPriceIncrease. The renewal email is a placeholder until
PM-37070 lands.

Also expands subscriptions.data.customer on the customer load so
PM-37064 can preserve customer-level discounts into Phase 2.

Incidentally strips pre-existing #region markers in
UpcomingInvoiceHandlerTests.cs per the no-regions rule.

* Apply review feedback: gate FF in handler, split MigrationPath checks, silence scheduler churn-only warning

* Add cohort metadata to subscription on migration schedule

---------

Co-authored-by: cyprain-okeke <108260115+cyprain-okeke@users.noreply.github.com>
2026-05-20 11:40:50 -05:00
Mike Amirault
f967279577 [PM-26732] Remove Chromium ABE importer feature flag (#7026)
* [PM-26732] Remove Chromium ABE importer feature flag

* Also remove older Chromium importer flag
2026-05-20 12:34:33 -04:00
Dave
25e78ceba3 [PM-35393] MasterPasswordService auth integration (#7575)
* feat(mp-service) Wire commands to MasterPasswordService.

* feat(self-service) Add logout-and-log to self-service command.

* feat(mp-service) Add dual-path request models and wire controller
routing.

Add structured cryptographic data support to all Auth password endpoints,
routing new payloads to MasterPasswordService-backed commands while
preserving legacy paths for backward compatibility (PM-33141 removal).

* refactor(mp-service) Mark legacy password entry points [Obsolete].

* test(mp-service) Add testing.

* refactor(mp-service) Rename ReplaceTemporaryPasswordAsync to be more descriptive.

* refactor(mp-service) Add variant validator and tests.

* fix(mp-service) Adjust payload variance validation.

* test(mp-service) Update integration tests to support payload variants and model validation returns.

* fix(password-request): Restore KDF regression guard.

* refactor(data-models): Collapse RequestHasNewDataTypes into local check.

* test(emergency-access): Update Emergency Access tests.

* refactor(mp-payload-variant-validator): Move to Auth utilities.

* test(self-service): Combine side-effects and password change into single test.

* feat(validation): Add kdf-salt agreement-only validation.

* refactor(password-request-model): consolidate onto ValidateKdfAndSaltAgreement.

* test(auth): Cover ValidateKdfAndSaltAgreement and enshrine legacy KDF acceptance.

* feat(validate-exclusivity): Throw on both payload variants present.

* test(accounts-controller): Update tests for exclusivity validation at the boundary.

* fix(request-models): Request models must accept both payload variants.

* PM-35393 - Add V2 dual-payload integration tests for password-modification flows

End-to-end coverage for the new AuthenticationData / UnlockData payload
across every endpoint that mutates a master password:

- POST /accounts/password — legacy-KDF acceptance, mismatch rejection,
  auth, current-password check.
- PUT /accounts/update-temp-password — legacy-KDF acceptance, mismatch
  rejection, auth, ForcePasswordReset precondition.
- PUT /accounts/update-tde-offboarding-password — sub-minimum KDF
  rejection (this flow intentionally enforces range), mismatch rejection,
  auth.
- POST /emergency-access/{id}/password — legacy-KDF acceptance, mismatch
  rejection, no-payload rejection, non-RecoveryApproved precondition.

Also extracts BuildAuthData / BuildUnlockData / BuildMismatchedAuthAndUnlock
helpers in AccountsControllerTest and rewrites the existing PostKdf_* tests
to use them (no behavior change).

15 new test methods, 41 cases. 155/155 controller-suite tests pass.

---------

Co-authored-by: Jared Snider <jsnider@bitwarden.com>
Co-authored-by: Jared Snider <116684653+JaredSnider-Bitwarden@users.noreply.github.com>
2026-05-20 12:28:30 -04:00
adudek-bw
cba2cc382e [PM-35948] Update send openapi to work for sdk (#7556)
* Update Send API calls
2026-05-20 12:02:46 -04:00
Stephon Brown
779320aabe [PM-37598] Update Tax Id Warning Logic with Feature Flag (#7677)
* feat(billing): inject feature service into billing warning queries

* test(billing): add provider tax warning tests for automatic tax flag

* test(billing): add organization tax warning tests for automatic tax flag

* feat(billing): modify provider tax id warning based on automatic tax feature flag

* feat(billing): modify organization tax id warning based on automatic tax feature flag

* refactor(billing): clean up unused usings and file encoding

* test(billing): add tax id verification warnings for providers

* test(billing): add tax id verification warnings for organizations
2026-05-20 10:02:51 -04:00
Nick Krantz
497e78542a [PM-35656] Add Events for New Item Types (#7642)
* add events for new item types hidden fields

* add events for collection
2026-05-20 08:01:56 -05:00
Thomas Rittson
543afdcd9a [PM-37740] Add missing container configuration to aspire (#7670) 2026-05-20 09:31:16 +10:00
Jordan Aasen
40d82aa0e2 remove legacy collections endpoint (#7520) 2026-05-19 14:36:39 -07:00
Alex Morask
466bf01148 [PM-37064] feat: Add ScheduleBusinessPriceIncrease scheduler entry point (#7665)
* [PM-37064] feat: Add ScheduleBusinessPriceIncrease scheduler entry point

Extends PriceIncreaseScheduler (PM-32645) with a parallel entry point for
Teams/Enterprise 2020 → current plan migrations under epic PM-35215. The
business path consumes a cohort directly, preserves existing discounts,
optionally appends the cohort's proactive coupon, and stamps ScheduledDate
on the assignment row on success.

Existing Schedule renames to SchedulePersonalPriceIncrease across four
call sites; ResolvePhase2Async becomes private. Shared concerns extract
into ActiveScheduleExistsAsync and CreateAndConfigureScheduleAsync helpers.

ScheduleBusinessPriceIncrease has zero production callers — the
UpcomingInvoiceHandler dispatcher branch lands in a follow-up. The new
PM35215_BusinessPlanPriceMigration feature flag defaults off.

* Address PR review: prevent orphan schedules and fix Release flag gate
2026-05-19 14:14:30 -05:00
Stephon Brown
e5419a7662 [PM-37597] Set Automatic Tax and Prevent Tax Exempt Mutations (#7662)
* feat(billing): add feature flag for automatic tax enforcement

* refactor(billing): remove unused SubscriptionUpdateOptionsExtensions

* refactor(billing): inject IFeatureService into billing services and commands

* feat(billing): conditionalize customer tax exemption logic with feature flag

* feat(billing): conditionally enable Stripe automatic tax in OrganizationBillingService

* test(billing): add unit tests for Stripe automatic tax feature flag

* fix(billing): Run dotnet format

* test(Premium): use class-level IFeatureService mock in UpgradePremiumToOrganizationCommandTests

* refactor(billing): consolidate customer return conditions for automatic tax

* refactor(billing): broaden postal code validation for organization creation

* refactor(billing): remove PM37597 feature flag for automatic tax logic

* Revert "refactor(billing): broaden postal code validation for organization creation"

This reverts commit cddbda838c.

* fix(test): remove outdated test
2026-05-19 13:18:06 -05:00
Vijay Oommen
627da54323 PM-36359 Feature flag for Splunk integration (#7622) 2026-05-19 11:31:13 -05:00
Vijay Oommen
78967f5730 PM-35058 created a new feature flag (#7657) 2026-05-19 11:30:56 -05:00
Oscar Hinton
4a3c20408d Add PAM feature flag (#7641) 2026-05-19 10:11:21 +02:00
Andy Pixley
fb3036e81a chore: trigger rebuild after cosign tlog 409 (#7669) 2026-05-19 00:10:34 +00:00
Thomas Rittson
766c33b3a6 [PM-37237] Move OrganizationsNew into ProfileResponseModel (#7627) 2026-05-19 07:46:40 +10:00
Nik Gilmore
808cef3e7e [PM-37723] Add feature flag pm-28191-cipher-admin-ops-to-sdk (#7664)
* [PM-37723] Add feature flag pm-28191-cipher-admin-ops-to-sdk

* Rename constant to use correct ticket number
2026-05-18 21:24:37 +00:00
Thomas Rittson
1c3dc375bd Move collections API code to AC Team (#7651) 2026-05-19 07:08:43 +10:00
Justin Baur
750b2219b5 [PM-36843] Skip relay push registration for non mobile clients (#7617)
* Fix null warnings and add more descriptive log in the case or non-successful HTTP calls.

* Add RelayPushRegistration tests

* Skip Push Registration when the client is not a mobile client

* Formatting

* Pin New Dependency

* Assert more in mobile test and use actual mobile device type
2026-05-18 14:48:50 -04:00
Alex Morask
d009a52f43 [PM-36949] feat: Add OrganizationPlanMigrationCohort and Assignment tables with bare repositories (#7644)
* [PM-36949] Add OrganizationPlanMigrationCohort schema and Core domain types

Add the foundation for cohort-based plan migrations:
- Two tables: OrganizationPlanMigrationCohort and OrganizationPlanMigrationCohortAssignment
- Two views and nine stored procedures (four CRUD on cohort, four CRUD plus
  ReadByOrganizationId on assignment)
- Single Migrator script for MSSQL deployment
- Core entities, MigrationPath value object and its registry, and bare repository
  interfaces under Bit.Core.Billing.Organizations.PlanMigration

The cohort table holds the human-managed metadata (name, discount coupons,
MigrationPathId byte) and the assignment table records each organization's
position in the migration lifecycle (scheduled, migrated, churn-mitigated).
Both Update SPs follow the accept-but-don't-assign pattern: immutable columns
(OrganizationId, CohortId, CreatedAt) are parameters but not SET clauses.

* [PM-36949] Add Dapper repositories for plan migration cohort tables

OrganizationPlanMigrationCohortRepository inherits the base Repository<T, TId>
CRUD methods unchanged. OrganizationPlanMigrationCohortAssignmentRepository
also relies on the base for CRUD and adds GetByOrganizationIdAsync which
returns at most one row (the UNIQUE constraint on OrganizationId at the
database layer guarantees this).

* [PM-36949] Add EF Core configurations, repositories, and provider migrations for plan migration cohort tables

- EF models wrap the Core entities; the assignment model exposes nav properties
  for Organization and Cohort so the FK + cascade-delete is inferred by EF.
- EntityTypeConfiguration classes pin ID generation to application code
  (ValueGeneratedNever) and declare the UNIQUE indexes plus the composite
  (CohortId, ScheduledAt, MigratedAt) index.
- Repositories follow the OrganizationInstallationRepository template; the
  assignment repo adds GetByOrganizationIdAsync to mirror the SP exposed on
  the MSSQL side.
- DatabaseContext gets two DbSet properties; auto-discovery picks up the
  configuration classes.
- Generated migrations for MySQL, Postgres, and SQLite create matching schemas;
  EF truncates FK and index names on providers with 64-char identifier limits,
  which is consistent with the rest of the codebase.

* [PM-36949] Wire up DI and add tests for plan migration cohort repositories

Register both Dapper and EF Core repositories in their respective service
collection extensions, following the existing AddSingleton convention in
these files.

Add tests:
- MigrationPathIdsSnapshotTests guards the immortal byte IDs that downstream
  code pins on. The class- and method-level comments document why these
  values can never be renumbered.
- MigrationPathTests covers the FromId round-trip and the null-on-unknown
  behavior the registry promises to callers.
- OrganizationPlanMigrationCohortRepositoryTests exercises CRUD, the UNIQUE
  Name constraint, and verifies that ReplaceAsync ignores CreatedAt
  mutations (per the accept-but-don't-assign Update SP).
- OrganizationPlanMigrationCohortAssignmentRepositoryTests exercises CRUD,
  GetByOrganizationIdAsync, the UNIQUE OrganizationId constraint,
  cascade-delete from both Organization and Cohort, and verifies that
  ReplaceAsync ignores OrganizationId, CohortId, and CreatedAt mutations.

* [PM-36949] Use PlanType and MigrationPathId enums on MigrationPath

Replace the byte Id with a byte-backed MigrationPathId enum and replace
the string FromPlan/ToPlan fields with PlanType. Persistence is
unchanged -- EF normalises enum-backed properties to their underlying
type in the model snapshot, and Dapper handles enum-to-byte parameter
mapping automatically.

* [PM-36949] Add *.lscache to .gitignore

* [PM-36949] fix: Override ReplaceAsync on EF cohort repositories for immutability parity

The Dapper _Update SPs accept-but-don't-assign certain columns (CreatedAt
on cohort; OrganizationId, CohortId, and CreatedAt on assignment), but
the base EF Repository<T,TEntity,Guid>.ReplaceAsync uses SetValues which
writes every scalar. Override on both repos and mark the immutable
properties as IsModified = false so MySQL/Postgres/Sqlite match MSSQL
behavior. Mirrors the existing DeviceRepository.ReplaceAsync pattern.

* [PM-36949] fix: Bound cohort string columns and widen Name to 255 chars

Add [MaxLength] attributes to the three cohort string properties so the
EF providers (MySQL/Postgres/Sqlite) enforce the same limits as MSSQL,
where the columns were already NVARCHAR-capped. Widen Name from 64 to
255 chars across MSSQL DDL, both _Create/_Update SP signatures, the
Migrator script, the entity, and all three regenerated EF migrations.
Coupon codes stay at 64 (Stripe IDs are short).

* [PM-36949] test: Lock FromPlan and ToPlan per MigrationPath

The snapshot test class doc says "byte N means a specific FromPlan ->
ToPlan transition forever", but only the byte value was being asserted.
A silent refactor of the registry's PlanType references would not have
been caught. Add per-path FromPlan/ToPlan assertions to close the gap.

* [PM-36949] chore: Apply dotnet format

* [PM-36949] test: Use LaxDateTimeComparer for round-tripped DateTimes

Postgres timestamp and MySQL datetime(6) store microsecond precision (6
fractional digits), but .NET DateTime is 100ns ticks (7 digits). Exact
Assert.Equal fails by a single tick on round-trip. Switch the three
DateTime comparisons in ReplaceAsync_UpdatesMutableColumns_AndIgnoresImmutableOnes
to LaxDateTimeComparer.Default -- the same 2ms-tolerance comparer used
by SendRepositoryTests and InstallationRepositoryTests for the same
precision issue.

* [PM-36949] refactor: Rename DateTime columns to Date suffix per naming convention

Addresses PR review feedback. Also tightens DATETIME2(7) / NVARCHAR(N) spacing
per the SQL style guide, drops *.lscache from .gitignore (handled by #7648),
and regenerates EF migrations for MySQL, Postgres, and SQLite.

* Apply dotnet format to regenerated migrations

* [PM-36949] chore: Align NULL/NOT NULL columns in cohort tables
2026-05-18 12:34:55 -05:00
github-actions[bot]
1d999ace63 Bumped version to 2026.5.0 (#7655)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Addison Beck <addison@bitwarden.com>
2026-05-18 17:14:31 +00:00
Stephon Brown
4224933c62 [PM-35357] Update Trial Length Parameter (#7597)
* test(billing): Add unit tests for TrialInitiationCache

* feat(billing): Add trial initiation cache interface and implementation

* feat(billing): Register trial initiation cache services

* feat(core): Add trial properties to OrganizationSignup model

* feat(mail): Update trial verification email model and services for TrialInitiationId

* feat(billing): Enhance TrialSendVerificationEmailRequestModel validation

* test(billing): Add tests for TrialSendVerificationEmailRequestModel validation

* feat(billing): Introduce default trial length constant

* refactor(identity): Use constant for default trial length in AccountsController

* test(identity): Update accounts controller tests for default trial length constant

* feat(billing): Integrate trial initiation into email sending command

* feat(billing): Add TrialLength to SubscriptionSetup model

* feat(billing): Map TrialLength in OrganizationSale creation

* feat(billing): Allow custom trial length in organization billing service

* feat(admin-console): Add TrialLength and TrialInitiationId to organization creation requests

* feat(admin-console): Validate trial length during cloud organization signup

* test(admin-console): Add tests for organization create request trial properties

* test(admin-console): Add tests for CloudOrganizationSignUpCommand trial length validation

* refactor(TrialInitiationCache): change validation method to retrieval

* test(TrialInitiationCache): update tests for GetAndRemoveAsync

* feat(OrganizationSignUp): refactor trial validation to command

* test(OrganizationSignUp): add trial validation scenarios

* test(OrganizationSignUp): nullify TrialLength in unrelated tests

* fix(billing): dotnet format

* refactor: remove `TrialInitiationId` property from data models
refactor: update mail service interfaces and implementations

* refactor: remove `ITrialInitiationCache` infrastructure
test: update `CloudOrganizationSignUpCommandTests` for trial validation

* refactor: update `SendTrialInitiationEmailForRegistrationCommand`

* refactor: update `CloudOrganizationSignUpCommand` trial length validation

* test(organization): fix plan call in tests

* test(billing): fix test settings
2026-05-18 09:32:04 -04:00
Jimmy Vo
c7c0ab2f1a [PM-19551] Add externalId support to groups PATCH endpoint (#7620) 2026-05-16 08:19:03 +10:00
Mike Amirault
85dc94a15e [PM-32743] Add ability to create folders during import to orgs (#7568)
* [PM-32743] Add ability to create folders during import to orgs

* Address PR comments

* Fix tests and lint

* Address AI review comments
2026-05-15 14:02:30 -07:00
Jared Snider
eb9c8c9aa9 Auth/PM-37621 - Fix Device.LastActivityDate surfacing legacy NULL rows as DateTime.UtcNow (#7649)
* PM-37621 - Fix Device.LastActivityDate surfacing legacy NULL rows as DateTime.UtcNow

Dapper's deserializer skips the property setter when a nullable column is
DBNull, leaving the property at its CLR default. The field initializer
`public DateTime? LastActivityDate { get; internal set; } = DateTime.UtcNow`
poisoned that default, so rows whose LastActivityDate column was NULL (e.g.
devices created before the column existed) read back as the current time.

Drop the initializer, relax `internal set` to `set`, and stamp
LastActivityDate explicitly at the two creation call sites
(DeviceValidator.GetDeviceFromRequest and DeviceRequestModel.ToDevice). Adds
an integration regression test that creates a device with an explicit null
LastActivityDate and asserts the read path surfaces null. Augments
DeviceValidatorTests.GetDeviceFromRequest_RawDeviceInfoValid_ReturnsDevice
to lock in the creation-time stamp.

* PM-37621 - DeviceSeeder - creation should set LastActivityDate
2026-05-15 16:34:08 -04:00
Dave
8e12a8e305 chore: ignore C# Dev Kit lscache and dump files (#7648)
Add *.lscache, *.dmp, and *.dump to .gitignore following the pattern
established in dotnet/runtime#126718 and tracked in
microsoft/vscode-dotnettools#2952.

*.lscache files are generated by the C# Dev Kit language server and
appear as untracked noise in any developer's working tree. *.dmp and
*.dump files are .NET memory dump artifacts that can be large and may
contain sensitive in-process data.
2026-05-15 19:56:06 +00:00
Stephon Brown
968afb53dd Aspire: Add README for Aspire AppHost setup and usage (#7646) 2026-05-15 15:55:49 -04:00
Jackson Engstrom
419edd55de [PM-26696] Removes pm-23904-risk-insights-for-premium feature flag (#7613) 2026-05-15 11:48:34 -07:00
Justin Baur
e131b1f243 Migrate to SLNX Style Solution (#7645) 2026-05-15 18:05:38 +00:00
Stephon Brown
20c913466b Aspire Integration (#6775)
* feat: Add Aspire Apphost and ServiceDefault projects

* feat: Add compiler conditional ServiceDefaults to included projects

* fix(billing): update otlexporter duplicate call

* fix(billing): update imports

* fix(billing): revert unintended changes

* fix(billing): revert unintended changes

* fix(billing): fix unintended files

* fix(billing): add apphost and extension methods

* fix(billing): update aspire

* fix(billing): update references to match integration test configuration version

* chore(billing): update secrets.json example

* refactor(Aspire): remove ServiceDefaults project

* build(AppHost): update Aspire SDK and add conditional community plugins

* refactor(AppHost): centralize resource orchestration calls to BuilderExtensions

* feat(AppHost): implement configuration-driven resource setup

* chore(dev): remove obsolete configuration from development files

* fix(billing): run dotnet format

* fix(billing): revert changes

* fix: solution spacing

* refactor(core): update discount models and extensions to use Source.Coupon

* refactor(core): update billing queries, commands, and responses to use Source.Coupon

* refactor(core): update billing services and handlers to use Source.Coupon

* test(billing): update discount mock structures and assertions to match Source.Coupon path

* chore(core): update Stripe.net dependency to version 51.1.0

* feat(billing): explicitly set classic billing mode for subscriptions and invoices

* test: simplify nullable datetime assertions in subscription tests

* test(billing): add coupon applies_to expansion assertions

* feat(providers): default new subscriptions to classic billing mode

* fix(billing): prevent clearing existing subscription metadata when none is provided

* style: remove BOM from BuilderExtensions.cs

* build: update Aspire and Ngrok package versions

* fix: gracefully handle missing BlobService in Azure storage configuration

* fix: correct Ngrok service tunnel endpoint for billing service

* Revert "Merge branch 'billing/pm-36225/upgrade-stripe-sdk-to-51.1.0' into billing/aspire"

This reverts commit a5b6f6a28d, reversing
changes made to 0c2f0e68ca.

* fix(billing): remove duplicate sql dependency

* fix(billing): run dotnet format

* refactor(AppHost): update ConfigureServices return tuple names and documentation

* build(project): remove TargetFramework from AppHost.csproj
2026-05-15 16:57:23 +00:00
Stephon Brown
b97744d9f1 chore(feature-flags): remove PM24032_NewNavigationPremiumUpgradeButton flag (#7558) 2026-05-15 11:16:34 -04:00
Graham Walker
7f637aade9 PM-37478 temporarily disabling useRiskInsights access controll (#7631) 2026-05-15 10:08:50 -05:00
John Harrington
d5bd9f3e63 Send creation logging (#7602) 2026-05-15 07:28:17 -07:00
Jared Snider
450159a1e2 Auth/PM-37166 - Devices - add client version (#7632)
* PM-37166 - Add ClientVersion to Device entity and repository contract

* PM-37166 - Add ClientVersion SQL schema and refactor bump stored procedures

* PM-37166 - Implement combined bump in repositories and add EF migrations

EF snapshot regeneration also absorbs Collection / CollectionGroup /
CollectionUser namespace moves (Bit.Infrastructure.EntityFramework.Models
-> Bit.Infrastructure.EntityFramework.AdminConsole.Models) that were left
un-regenerated by PR #7523 (PM-35489). Namespace-only, no SQL impact;
flagged with the AC team for awareness.

* PM-37166 - Replace DeviceLastActivityCacheService with DeviceDataCacheService

* PM-37166 - Replace BumpDeviceLastActivityDateCommand with BumpDeviceDataCommand

* PM-37166 - Pass ClientVersion through identity request validators

* PM-37166 - Align migration script with SQL style guide

Refresh Device_ReadBy* sprocs after DeviceView change so their cached
schema picks up ClientVersion, swap retired-sproc drops to
DROP PROCEDURE IF EXISTS, and tighten the ALTER TABLE indent in step 1.

* PM-37166 - Rename BumpData to UpdateLastActivity across device write pathway

The "BumpData" naming was vague — "data" named a category, not the thing
being written. Rename to "UpdateLastActivity" everywhere: SP, repositories,
command, cache, validators, tests. "Last activity" names the event of the
device's most recent appearance; LastActivityDate (when) and ClientVersion
(what was running) are facts we observed about that event. ClientVersion is
treated as a property of the activity event rather than an independent value,
so future last-observed properties (last IP, OS, etc.) slot in without renaming.

The SQL layer uses Update* per architect guidance on bitwarden/server#7302;
the Bump* SPs in this codebase are legacy and not being extended. The
extensibility note lives on IUpdateDeviceLastActivityCommand with short
pointers from the SP, repo, and cache.

Cache key prefix changes from device:data: to device:last-activity: — safe
because the cache is only a write-suppression optimization (SP guards ensure
correctness) and entries TTL out within 24h.

Migration renamed to 2026-05-14 to reflect the rewrite.

* PM-37166 - Add UTF-8 BOM to device last activity cache files

Aligns file encoding with the repo's .editorconfig (charset = utf-8-bom for .cs) so dotnet format --verify-no-changes passes.

* PM-37166 - Compare LastActivityDate at second precision in device creation test

GetManyByUserIdWithDeviceAuth_ReturnsLastActivityDate_ForNewDeviceAsync was
flaking on SqlServer: Dapper binds DateTime params as legacy `datetime`
(~3.33ms granularity), so the entity initializer's UtcNow can be rounded a
few ms earlier than the in-memory `beforeCreation` capture, making a strict
>= comparison occasionally false. Truncate both sides to the second to
absorb that drift while still rejecting stale or defaulted values.

* PM-37166 - Rename Device.ClientVersion EF migration

Renames migration class/files from AddDeviceClientVersionRefactorDeviceDataBump
to AddDeviceClientVersion to drop stale "Bump" terminology and the misleading
"RefactorDeviceData" prefix. The EF migration only adds the ClientVersion
column; the BumpData -> UpdateLastActivity SP refactor lives in MSSQL .sql
files and has no EF representation.

* PM-37166 - Document null-is-no-op semantics for ClientVersion on IUpdateDeviceLastActivityCommand

Tighten the interface-level summary and add a <param> note clarifying that
a null clientVersion is treated as "no opinion" and will not clear an
existing stored value.

* PM-37166 - Regenerate Device.ClientVersion EF migration on post-#7634 baseline

PR #7634 merged AddLastApiKeyRotationDateToUserTable into main while this
branch was open. The prior AddDeviceClientVersion migration's frozen model
snapshot (its .Designer.cs) was generated before that PR landed, so it did
not include User.LastApiKeyRotationDate. Applying migrations incrementally
against that stale snapshot would produce an inconsistent model graph.

Regenerated AddDeviceClientVersion on top of the merged-from-main baseline
so the new .Designer.cs files include both columns. The migration body
itself still only adds Device.ClientVersion; the top-level
DatabaseContextModelSnapshot.cs files were already correct from git's
three-way merge.

New timestamps (20260514192xxx) come after the User migration
(20260514011xxx), preserving migration order.

* PM-37166 - util/Migrator/DbScripts/2026-05-14_00_AddDeviceClientVersionAndUpdateLastActivitySp.sql - fix wrong comment

* PM-37166 - Bump Device.ClientVersion column width from 20 to 43

43 is the upper bound of Version.ToString() for any input parseable by
Version.TryParse — four Int32 components (Int32.MaxValue = 10 digits)
joined by 3 dots. Sizing to the type's mathematical max prevents
SQL Server error 8152 on malformed/hostile Bitwarden-Client-Version
headers without paying the cost of normalization at the call sites.

Real Bitwarden CalVer (YYYY.M.B) remains well within bounds at ~9 chars.

- Device.cs [MaxLength] + entity doc comment
- SSDT table + 4 stored procedures
- Cloud migration ALTER TABLE + SP parameters
- EF migrations regenerated for MySQL / Postgres / SQLite

* PM-37166 - Defer dropping old single-column UpdateLastActivityDate SPs to follow-up

Server and DB deploys are decoupled, so dropping the old SPs in the same migration that
introduces the new combined ones would break server rollback. Per discussion on PR #7632:

- Remove DROP PROCEDURE statements from the migration; replace with a note explaining the deferral.
- Restore the old Device_UpdateLastActivityDate{ById,ByIdentifierUserId}.sql files in src/Sql/dbo
  so the SSDT source-of-truth stays aligned with deployed schema (EDD).

A follow-up ticket will drop the old SPs and delete the .sql files together once we're
confident no deployed server version still calls them.

* PM-37166 - Pass @LastActivityDate into Device_UpdateLastActivity SPs

Bitwarden convention is to compute timestamps in the application layer
and pass them as DATETIME2(7) params, not call GETUTCDATE() inside SPs.
Dapper repo now computes DateTime.UtcNow locally (matching the EF repo
and UserRepository.cs precedent) and passes LastActivityDate through.
2026-05-14 20:22:13 -04:00
Jackson Engstrom
7a2cafb2fd [PM-26657] Removes feature flag pm-25083-autofill-confirm-from-search (#7610) 2026-05-14 14:09:09 -07:00
Jordan Aasen
d92cd445cd add feature flag (#7630) 2026-05-14 11:45:58 -07:00
Jared Snider
f3e4f5cd4e Auth/PM-37165 - Add Last API Key Rotated Date to User (#7634)
* PM-37165 - Add LastApiKeyRotationDate column to User

Adds a nullable DATETIME2(7) LastApiKeyRotationDate column on the User
table alongside the other Last*Date audit columns. Covers the MSSQL
table, view, User_Create / User_Update stored procedures (new optional
parameter, EDD-safe with default NULL), the SSDT source-of-truth, and
EF migrations for MySql, Postgres, and Sqlite.

Repository round-trip integration tests verify that CreateAsync
defaults the column to NULL and ReplaceAsync persists it across all
four providers.

* PM-37165 - Add RotateUserApiKeyCommand under Auth/UserFeatures

Extracts user API key rotation out of UserService into a new CQS
command at src/Core/Auth/UserFeatures/UserApiKey/, mirroring the
existing decomposition pattern for other Auth user features. The
command generates a new 30-char ApiKey, bumps RevisionDate, sets
LastApiKeyRotationDate, and persists via IUserRepository.ReplaceAsync.

Adds the PM37165_RotateUserApiKeyCommand feature flag so the new path
can be rolled out behind a flag in a follow-up commit. Registers the
command via AddUserApiKeyCommands inside AddUserServices.

Unit tests verify the command assigns a fresh key, updates both
RevisionDate and LastApiKeyRotationDate to the same recent UTC value,
and calls ReplaceAsync exactly once.

* PM-37165 - Flag-gate rotate-api-key endpoint to new command

Wires AccountsController.RotateApiKey to dispatch between
IRotateUserApiKeyCommand (flag on) and the legacy
UserService.RotateApiKeyAsync (flag off) based on
PM37165_RotateUserApiKeyCommand. Both paths preserve the existing
auth and secret-verification guards, which run before the flag
branch.

Marks IUserService.RotateApiKeyAsync and its implementation [Obsolete]
pointing callers at IRotateUserApiKeyCommand, with TODOs tying their
removal to the flag cleanup. The body of the legacy method is
deliberately unchanged so it does NOT write LastApiKeyRotationDate
while the flag is off; that genuinely gates the new behavior so the
ramp is observable and reversible. The single remaining call site
(the controller fallback) is wrapped in #pragma warning disable
CS0618 so the attribute continues to flag any new callers.

Tests:
- AccountsControllerTests: dispatch tests for both flag states; the
  auth and bad-secret guard tests are parameterized over flag state.
  Pre-existing typo in two tests that called _sut.ApiKey() instead of
  _sut.RotateApiKey() is fixed.
- UserServiceTests: regression test locks in the legacy non-write
  behavior so it cannot drift before the flag is removed.
- AccountsControllerTest (integration): three endpoint tests cover
  flag-off (LastApiKeyRotationDate stays NULL), flag-on (column is
  populated), and bad-secret over both flag states (no rotation
  occurs).

Each flag-state-specific test carries a TODO breadcrumb describing
the exact rename or deletion when the flag is cleaned up.

* PM-37165 - Tweak comment

* PM-37165 - Move LastApiKeyRotationDate to end of User schema

Append the new column to the end of User.sql, UserView.sql, the
matching CREATE OR ALTER VIEW in the migrator script, and the User
entity so SSDT mirrors what ALTER TABLE ADD produces in production.
2026-05-14 14:31:16 -04:00
cyprain-okeke
b0dd1c9d16 [PM 34174]Do not show renewal reminder banners to exempt organizations (#7483)
* expose the ExemptFromBillingAutomation to client

* Fix the failing database

* Rename the file to resolve chronological order error

* Renamed the migration file name

* fix the failing database

* Suppress warnings for exempt orgs at the query level

Gate InactiveSubscription and ResellerRenewal warnings inside
GetOrganizationWarningsQuery on Organization.ExemptFromBillingAutomation
instead of plumbing the field through the profile response, view models,
EF queries, and SQL views.

* Add the ExemptFromBillingAutomation property

---------

Co-authored-by: Alex Morask <144709477+amorask-bitwarden@users.noreply.github.com>
2026-05-14 18:22:08 +01:00
Maciej Zieniuk
9548272fce Allow key rotation for Key Connector users (#7618) 2026-05-14 18:46:34 +02:00
Jared
dd4acb6dc8 [PM-35300] fix emails do not match figma (#7609)
* Refactor admin reset password email templates and update email service message

- Updated Handlebars and MJML templates for the admin reset password email to improve clarity and user instructions.
- Enhanced the text version to provide step-by-step recovery instructions.
- Modified the email service to reflect the organization name in the email subject line.

* Update admin reset password email template to adjust font size for clarity

* Adjust font size in admin reset password email template for improved readability

* Enhance admin reset password email by adding WebVaultUrl and SiteName to the model for improved context and user experience.

* Refactor admin reset password email templates for clarity and user guidance

- Updated text and Handlebars templates to improve messaging around account recovery steps.
- Adjusted links to direct users appropriately based on password reset status.

* Update admin reset password email templates to reflect changes in recovery link logic

- Modified Handlebars and MJML templates to adjust the recovery link based on the two-factor reset status.
- Ensured consistency in messaging across HTML and text versions of the email.

* Update HandlebarsMailService to use email as UserName for account recovery
2026-05-14 11:32:45 -04:00
Alex Dragovich
162f270670 [PM-37230] remove FF logic from new send endpoints (#7621) 2026-05-14 07:57:27 -07:00
Matt Bishop
91b833cb9d Seeder progress indicators (#7510) 2026-05-14 05:59:54 +02:00
Thomas Rittson
195a712b6d [PM-37482] Disable migration tester (#7633)
This produces inherently flaky tests because it works by 
fully migrating a database, and then re-running a specified
migration (the data migration) out of order. This means that
subsequent changes to the db schema will cause the migration
tests to fail, because the data migration will be re-run after
the schema has changed. Needs to be fixed before use.
2026-05-13 19:36:32 -05:00
Derek Nance
291ddfde97 Change where Setup container looks for openssl config (#7623) 2026-05-13 09:05:49 -05:00
Amy Galles
fcb08cf5c0 Fix/repository management remove tokens (#7626)
* Remove BW-GHAPP tokens from repository-management workflow

- Remove all Azure Key Vault and BW-GHAPP token generation
- Use github.token instead of app token
- Use github-actions[bot] email instead of actions@github.com
- Create PR with version bump instead of pushing directly to main
- Update permissions (remove id-token, add pull-requests for bump_version)
- No GPG signing to remove (wasn't present)

* Fix
       template injection security issue

* Remove BW-GHAPP tokens from repository-management workflow

- Remove all Azure Key Vault and BW-GHAPP token generation
- Use github.token instead of app token
- Use github-actions[bot] email instead of actions@github.com
- Create PR with version bump instead of pushing directly to main
- Update permissions (remove id-token, add pull-requests for bump_version)
- Add 'version update' label to automated PRs
- Fix template injection security issue
2026-05-13 09:46:42 +02:00
Amy Galles
ae99790366 Remove BW-GHAPP tokens from repository-management workflow (#7624)
- Remove all Azure Key Vault and BW-GHAPP token generation
- Use github.token instead of app token
- Use github-actions[bot] email instead of actions@github.com
- Create PR with version bump instead of pushing directly to main
- Update permissions (remove id-token, add pull-requests for bump_version)
- No GPG signing to remove (wasn't present)
2026-05-12 17:11:49 -05:00
Thomas Rittson
e4f82284cf Remove plan file (#7625) 2026-05-12 21:45:18 +00:00
Alex Morask
316f7cdc6c [PM-36613] Void open invoices for unpaid subscriptions (#7589)
* fix(billing): void open invoices when subscription is deleted

* refactor(billing): gate invoice voiding on subscription deletion

* feat(billing): clear pending unpaid cancellation on subscriber re-enable

* feat(billing): schedule unpaid cancellation on subscriber disable

* fix(billing): respect subscription test clock when scheduling cancellation
2026-05-12 21:29:57 +00:00
John Harrington
1f030a578c [PM-37077] Remediate Data Protection errors in DeleteSendsJob (#7608)
* skip unused unprotect on emails & log failures

* filter on unprotect success
2026-05-12 14:02:49 -07:00