Unified self-service role toggle RPC action.
One static request_response action — self_service_role_set — that
takes {role, enabled} and toggles a global permit on the caller for an
allowlisted role. Idempotent in both directions: re-enabling an
already-held role returns changed: false; disabling a role the caller
doesn't hold returns changed: false.
The factory takes an eligible_roles allowlist (validated against the
supplied roles.role_options at factory time so typos surface at startup
instead of at first call). Roles outside the allowlist are rejected
with forbidden + reason role_not_self_service_eligible.
Audit metadata carries self_service: true so admin reviewers can
distinguish self-toggled permits from admin grants/offers. The
permit_grant / permit_revoke metadata schemas declare
self_service: z.boolean().optional() explicitly, so the field is
part of the documented schema surface and is round-trip-validated by
query_audit_log.
Static method name — role lives in the input, not the method name —
so the spec is codegen-compatible (satisfies RequestResponseActionSpec)
and the surface stays constant as consumers add eligible roles. Mirrors
the existing permit_offer_create({role}) precedent rather than
generating per-role methods.
Specs and schemas live in auth/self_service_role_action_specs.ts so
client-side codegen can import the surface without dragging in the
query layer.