SmallWorlds v1.2.42
A single fix, to the identity layer: member onboarding and recovery-code login could not work, on any cluster whose realm came from this repo's import.
What was broken
smallworlds-realm.json used three identifiers Keycloak does not have. The admin API accepts an unknown provider id without complaint and stores it as a realm row that reads back as enabled: true, so every static check passed and the failure surfaced only when a member clicked their onboarding link:
| in the realm | what Keycloak calls it |
|---|---|
recovery-auth-code-register |
CONFIGURE_RECOVERY_AUTHN_CODES |
recovery-auth-code-form |
auth-recovery-authn-code-form |
| (absent) | UPDATE_PROFILE |
UPDATE_PROFILE was missing outright: a realm import replaces Keycloak's default required-action set, and the import listed only four providers — while admin-tools/bulk-invite.py asks for that action on every invitation. Every link the script has ever produced failed with "Required actions included in the link are not valid."
The authenticator id sat in the bound login path (browser → forms → passkey-or-password → must-authenticate), so recovery-code login was dead too — the only fallback a passwordless realm has.
Also fixed: VERIFY_EMAIL no longer sets defaultAction, which had been attaching a pending action to every account created on a cluster with no mail (docs/adr/0049). It stays enabled, so self-registration mode still triggers it through realm-level verifyEmail.
What operators need to do
Bumping to this tag is not enough for an existing cluster. realm-config-job.yaml creates the realm only if it is absent and never updates an imported one, so a cluster already running keeps the broken identifiers after the bump. Those need the corrections applied to the live realm by hand — register UPDATE_PROFILE and CONFIGURE_RECOVERY_AUTHN_CODES as required actions, drop the phantom recovery-auth-code-register row, and replace the must-authenticate execution with auth-recovery-authn-code-form (a newly added execution lands at priority 0, ahead of the passkey, so it needs an explicit lower-priority call).
New clusters get all of it from the import.
Verified against a running Keycloak on a LAN cluster: every authenticator id in the realm now resolves against the live provider list, and an invitation link renders "Update Profile, WebAuthn Register Passwordless, Generate Recovery Codes" and completes through passkey registration.
Housekeeping
invite-links.csv and invite-qr/ are now git-ignored. bulk-invite.py writes them 0600 because each row logs its holder into that member's account, but nothing had stopped them being committed.
Bootstrap inputs are unchanged from v1.2.41: k3s v1.36.2+k3s1, Argo CD v3.4.5, both digests re-verified against their official sources.