Soul fixes on PR #85: junk from a session thief no longer burns the member's ticket, challenge or verification permits; a passkey revoked between
assertion and completion does not unlink; PasskeyRelyingParty is resolved at startup and rejects an ExpectedHost with a port; with a strong passkey and an
unavailable RP the page shows a message instead of a dead form; Label() cuts by text element and drops format characters. Tests for each, the user-handle
owner callback, the account-scoped lookup (allow list stripped through the ceremony store) and the ticket cookie SameSite.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Heimdall-backed members enrol WebAuthn passkeys on the Linked accounts page (ticket from a fresh ordinary Heimdall sign-in, 48 h cooling-off, cap 5,
FixedWindowBudget on ceremonies) and unlink with a strong passkey: the assertion is verified at Bifrost, then inside the completion that holds the bearer
Bifrost calls Heimdall's POST /v1/apps/bifrost/step-up and the unlink with the returned token. The Google step-up closes once a strong passkey exists.
Migration AddPasskeyCredentials is additive. Tests use a software authenticator and a fake Heimdall step-up route modeled on the contract.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>