* LANG-145: bind WebAuthn to server config and make passkeys OSS-only
Two problems in the passkey implementation:
1. The RP ID and expected origin came from the request: a JSON 'origin' field,
then the Origin/Referer headers, then the request URL. WebAuthn's
anti-phishing guarantee depends on values the server chose; trusting the
request lets a sibling host under the same registrable domain obtain a valid
assertion for a victim's credential. Resolution now follows the same rule the
OAuth and invitation links already use: api.webui_url, then
api.webhook_prefix, then the configured port on loopback.
2. Passkeys are now an OSS-only feature. Cloud deployments authenticate through
their own account service, so every passkey route (register options/verify,
auth options/verify, list, rename, delete) refuses with
edition_unsupported, and /account-info advertises neither passkey_login_enabled
nor passkey_supported. Both cloud flavours are covered: system.edition ==
'cloud' and deployment.mode == 'cloud'.
Tests:
- New unit suite for the edition matrix and for origin resolution (including
that client-supplied origin/Origin/Referer are ignored).
- The three 'reverse proxy scenario' tests asserted the old, unsafe behaviour
(server trusting the request). They now assert the server-config contract.
- test_smoke cloud capabilities expectation updated to passkey_* = false.
Co-authored-by: multica-agent <[email protected]>
* style(api): drop the typing import left unused by the WebAuthn origin change
Co-authored-by: multica-agent <[email protected]>
---------
Co-authored-by: multica-agent <[email protected]>