The page imported it on its own as well, which is what broke the CAPTCHA rendering fixed by #5992 on the old password registration page. Also test that the page renders with a CAPTCHA configured.
The registration page had two steps: `/register` picked between a password
and an upstream provider, then `/register/password` collected the username,
email and password. Both now live on `/register`, whose `POST` handler runs
the provider branch first and otherwise hands the form to the registration
body, which stays in `password.rs` as a helper.
The page renders the username, email, password and terms-of-service fields,
the captcha and the provider buttons in a single form. The provider buttons
submit that same form, so they are marked `formnovalidate` to skip the
validation of the fields they do not use, and come after the primary submit
button so that Enter still registers.
`/register/password` is gone; a `GET` on it redirects to `/register` with the
query string it was given, so bookmarks and links keep working. Its
`?username=` prefill has no producer left and is dropped.
`GET /register` now renders the page whenever password registration is
enabled, instead of redirecting to `/register/password` when there is no
upstream provider. Without password registration, a single provider still
gets redirected to directly, and no provider at all now redirects to
`/login`, where `/register/password` used to send that case.
An unknown or disabled provider gives a 404 through an inline `GenericError`
rather than the route-wide `RouteError`, and an expired CSRF token on the
password path now sends the user back to `/register` instead of failing the
request.
The registration page is about to render the password registration form
itself, so its context needs the form state and the captcha configuration
`PasswordRegisterContext` carries today.
ulid 3 moves to `rand` 0.10, so it no longer pulls the `rand` 0.9
generation. Only `opentelemetry_sdk` and `sentry` still need it.
ULID generation keeps going through `UlidExt`, whose bit layout matches
ulid's own `from_datetime_with_source`. The only API change affecting
MAS is the rename of `Ulid::new` to `Ulid::generate`, which the clippy
ban list now targets.
`rand` 0.10 and the new RustCrypto generation both build on `rand_core`
0.10, so they have to move together:
- `rand`, `rand_chacha` and `rand_core` 0.10
- `digest` 0.11, `sha2` 0.11, `hmac` 0.13, `const-oid` 0.10
- `elliptic-curve` 0.14, `ecdsa` 0.17, `p256`, `p384` and `k256` 0.14,
`signature` 3
- `der`, `spki` and `sec1` 0.8, `pkcs8` 0.11, `pem-rfc7468` 1.0
- `rsa` 0.10.0-rc.19 and `pkcs1` 0.8.0-rc.5, which have no stable
release yet. They are pinned exactly, because release candidates
break their API between releases.
- `argon2` 0.6 and `pbkdf2` 0.13
On the `rand` side, `RngCore` becomes `Rng` and the old `Rng` becomes
`RngExt`. `gen_*` becomes `random_*`, `thread_rng` becomes `rng`,
`distributions` becomes `distr`, and `from_rng` can no longer fail. On
the crypto side, `mas-jose` and `mas-keystore` move to `BoxedUint` for
RSA, to the `pkcs1` and `pkcs8` reference types, and to the `Generate`
trait for key generation, and `mas-jose` no longer depends on
`generic-array`. Password hashing goes through `hash_password_with_rng`.
Stored data is unaffected. The password hashing snapshots are unchanged,
so bcrypt, Argon2 and PBKDF2 produce the same hashes for the same input
and salt, and `pbkdf2` 0.13 keeps the same defaults (SHA-256, 600 000
rounds). The keystore snapshots change only because keys generated from
a seeded RNG differ. The snapshots of keys loaded from files are
unchanged.
`opa-wasm` 0.3.3 already uses this generation, so most of the duplicate
crates it pulled in go away. The `deny.toml` skip list now names what
still pulls the older versions: cookie, sqlx, headers, wasmtime and pest
for RustCrypto, and opentelemetry_sdk, sentry and ulid for `rand` 0.9.
It moves from `generic-array` to `hybrid-array`, so `Encrypter` builds
its key and nonce with the `Key` and `Nonce` aliases, and `mas-keystore`
no longer depends on `generic-array`. Cookie (via `aes-gcm`) is still on
`aead` 0.5, so the older `aead` and `universal-hash` go on the cargo-deny
skip list.
The hashes it produces are unchanged. It pulls `blowfish` 0.10, which is
on `cipher` 0.5 while the rest of the tree is on 0.4, so the older
`cipher` and `inout` go on the cargo-deny skip list.
The `cargo deny` bans check fails on main because two dependency bumps
introduced duplicate crate versions:
- `opa-wasm` 0.3.3 (#6029) uses `rand` 0.10, `base64` 0.23 and the
`digest` 0.11 generation of the RustCrypto crates, while the rest of
the tree is still on `rand` 0.9, `base64` 0.22 and `digest` 0.10.
- The icu bump (#6015) pulls `zerovec-derive` 0.11.6, which uses `syn` 3,
while everything else is on `syn` 2.
Add the older versions to the skip list until the rest of the tree
catches up.
Two registrations with the same metadata could both miss the `find_by_metadata_digest` lookup and then race on the insert, the loser failing with a unique violation on `oauth2_clients_metadata_digest_key` and getting a 500.
`OAuth2ClientRepository::add` becomes `add_or_reuse` and inserts with `ON CONFLICT (metadata_digest) DO UPDATE ... RETURNING`, which yields the existing client when the digest is taken, including one committed while the insert was waiting on it. It reports whether it inserted, so the registration handler drops its lookup and still tells created and reused clients apart in the metric. `find_by_metadata_digest` has no callers left and is removed.
The returned client is now built from the database row, so it carries the metadata digest instead of always `None`, and the span records the id of the client actually returned.