* Add the account recovery V2 upgrade routes
GET /organizations/{orgId}/users/keys/pending-v2-upgrades lists, a page at a
time, the memberships whose account recovery key still wraps the member's V1
user key after an upgrade to V2 encryption, with the upgrade token the admin
re-wraps it from. POST .../v2-upgrades stores the re-wrapped keys in one
transaction, or unenrolls the members whose token holds no usable key. Only
Owners and Admins, an Admin never for Owners, and a membership that changed
since the read is skipped. GET /organizations/{orgId}/private-key gives the
organization's private key these need, to everyone with Manage users as
upstream. The SDK's encrypted migrator calls all three.
Enrolling in or withdrawing from account recovery drops a leftover upgrade
token, which would otherwise get a member who re-enrolled after the upgrade
unenrolled.
* Check membership for the organization public key in the handler
The public key routes serve the placeholder SSO organization's key to users
without an organization, so they couldn't require the member guard, but it
still ran for every request: it logged a membership error for each legitimate
v2 JIT password setup and authenticated the request twice. The routes now
authenticate once, return the placeholder key first, and check the membership
themselves, with the same rule as the guard.
* List attachments in sync with a stable URL
Sync and the cipher responses list each attachment with an unsigned URL of
upstream's form, which no longer changes on every sync nor costs a presign per
attachment on S3, and which isn't served without a token. The attachment routes
sign it: the cipher route and its admin variant, and the emergency access view's
route the web vault downloads through, which is added. The admin variant also
signs it for a member who can open the item themselves, because the web vault's
fallback to the listed URL no longer works.
* Seed the SDK live tests' vectors with their attachments
Sync now lists attachments with a stable URL, so the rotation test's before and after comparison holds with them.
Only the legacy attachments without a key of their own stay out: the SDK refuses to rotate a vault holding one.
* Add a test seeder behind the unsafe_test_mode feature
For the end-to-end tests: with the feature, /test/seeder answers the calls the
SDK's live tests make to a seeder API (POST /seed with SingleUserScene or
TestVectorUserScene, DELETE /seed/<playId>), behind HTTP basic auth from
TEST_SEEDER_USERNAME and TEST_SEEDER_PASSWORD, and 404 without them.
It creates accounts without any checks, so no release build has the feature.
CI builds and tests it with sqlite.
* Run the SDK live tests against the test seeder
tools/sdk-live-tests/run.sh builds the server with unsafe_test_mode and runs
the live tests of the SDK's e2e/wasm suite. For SDK versions whose tests log in
to one given account, each user test vector with a master password is seeded
with its vault on a fresh server; for versions that seed their own accounts,
the tests get the seeder's address. Every vector runs, then a summary.
The workflow runs it by hand, and on changes to the seeder or the runner.
* Run the SDK live tests daily
* Test the published SDK package by default in the SDK live tests
- Update Rust to v1.94.1
- Updated all crates
- Update GHA
- Update global domains and ensure a newline is always present
Signed-off-by: BlackDex <black.dex@gmail.com>
* Change API inputs/outputs and structs to camelCase
* Fix fields and password history
* Use convert_json_key_lcase_first
* Make sends lowercase
* Update admin and templates
* Update org revoke
* Fix sends expecting size to be a string on mobile
* Convert two-factor providers to string
- Update all crates
- Update GHA
- Update Global Domains script to use main instead of master
Also fixed some Python linting warnings
- Updated Admin JS and CSS libraries
The script works by reading the relevant files from the upstream Bitwarden
source repo and generating a matching JSON file. It could potentially be
integrated into the build/release process, but for now it can be run manually
as needed.