Support Staff
Support staff view as a member of any org in the deployment ("view as") without being members of that org. Two reserved roles grant it, both held at deployment scope only:
| Role | May start | While viewing as someone |
|---|---|---|
saaslayer:support-view-only | view-only sessions | every write is refused (403 VIEW_ONLY_IMPERSONATION); reads run as the person viewed |
saaslayer:support-act-as | view-only and act-as sessions | act-as also runs the person's writes; reserved operations stay refused (RESERVED_UNDER_IMPERSONATION) |
Each role holds saaslayer:users:account:impersonate and the reads that find whom to view as, all at deployment scope:
saaslayer:users:account:read (user-service GET /api/users?email=), saaslayer:identity:user:read (Permissions
GET /users/{id}/orgs), saaslayer:orgs:org:read (GET /orgs, GET /orgs/{id}) and saaslayer:orgs:member:read
(GET /orgs/{id}/members). No write of any kind. Holding impersonate
makes its holder a protected target: nobody views as support staff.
Granting and revoking
Only an access admin signed in themselves grants or revokes a support role (never an API key, an IAM machine, a delegated session or an impersonated one), at deployment scope, optionally until an expiry. A customer org owner, an org-scoped role administrator and support staff themselves cannot grant, widen or revoke support access, their own included.
saaslayer users get --email support@acme.com --deployment dep_… # find the suid
saaslayer permissions support-staff grant <suid> --mode act-as --expires-at 2027-01-01T00:00:00Z --id-token-file id.jwt --deployment dep_…
saaslayer permissions support-staff list --deployment dep_…
saaslayer permissions support-staff revoke <suid> --mode act-as --id-token-file id.jwt --deployment dep_…The CLI calls the role assignment routes: POST /users/{id}/roles {"roleId":"saaslayer:support-act-as","expiresAt":"…"},
DELETE /users/{id}/roles/saaslayer:support-act-as, and GET /roles/{id}/assignments (platform callers only) for the list.
Sessions and modes
A session starts with session.impersonate({ targetSuid, orgId, mode }) (@saaslayer/js). orgId is the target's org;
the session acts only inside it. The server checks the mode against the actor's grant and owns it from then on:
- an omitted or unknown
modestarts view-only, so an older client never acts; - a
support-view-onlyholder asking foract-asis refused (403 FORBIDDEN, reasonmode_not_allowed); - the token carries the mode in
custom:as_mode; Permissions and the server SDK (HTTP and direct) treat a token whosecustom:as_modeis missing or unknown as view-only; - refreshes keep the session's mode and end time and re-check the grant: a revoked grant, or
act-asremoved from it, ends the session at the next refresh with a clean token. A token already issued stays usable until its own expiry (at most the pool's token lifetime) or the session's end, whichever comes first; useImpersonation()(@saaslayer/react) exposesmodeandendsAt.
Members who hold impersonate in their own org keep today's rule (they must belong to the org) and may start either mode.
Settings
| Setting | Default | Meaning |
|---|---|---|
user-service.ImpersonationEnabled | false | impersonation is off until the deployment turns it on |
user-service.ImpersonationMaxSeconds | 900 | how long a new session lasts, 60 to 86400 seconds; fixed when it starts |
user-service.ImpersonationAuditVisibleToCustomer | false | record session start and end, with the real actor and the mode, in the customer's org audit feed |
Sessions are always logged by user-service (impersonate:audit lines) whatever the visibility setting.
Writes made while viewing as someone are recorded in the org's audit log with the person viewed as the actor and the staff
member as realActor. The staff member's name and email are stored, but customers should see only the deployment's
support label (permissions-service.SupportLabel, default Support), as <sl-audit-log> shows it: see
Staff in the audit log.