feat: multi-IdP claim-shape support (roles_claim_path + token validation mode)
Scope
Per-IdP roles_claim_path field in idp.toml + canopy_auth claims-extraction generalization so non-Keycloak IdPs (authentik, zitadel, kanidm, generic OIDC with custom realms) emit role claims at IdP-specific paths.
Background
Stage 4 (#493 (closed)) narrowed provider_type enum to keycloak | oidc-generic because WorkerRole::from_keycloak_roles (services/canopy-web/src/session.rs:28-40) hardcodes Keycloak's realm_access.roles claim shape. This issue unblocks the full set of OIDC backends (authentik, zitadel, kanidm).
Note: per-IdP audience already ships in Stage 4 ([[idp]].audience field is required). This FU is specifically the roles claim path + token validation mode plumbing.
Acceptance
-
IdpEntry.roles_claim_path: Option<String>(defaultrealm_access.roles) -
WorkerRole::from_claims(&claims, &roles_claim_path)generalized lookup -
ProviderTypeenum widened tokeycloak | authentik | zitadel | kanidm | oidc-generic - Per-IdP integration tests against each backend type
- CHANGELOG entry