Managing users
Add, remove, reshape, and audit the people in your organization from a single table at /admin/users.
The Users page is the most frequently used surface in the admin console. It lists every user whose email domain matches the organization, lets you make point edits from a row menu, and lets you act on many people at once with bulk operations.
The Users table
The table at /admin/users shows one row per user with these columns:
- User — display name plus email. The display name is the SSO name unless an admin has set an override.
- Role — the role assigned to the user. The built-in
adminrole gets a gold pill; other roles render as the role name. - DB Permission — the user's default database permission tier (
viewer,editor, oradmin). This column only appears when your organization has at least one SQL Server connection. See Roles and permissions for what each tier allows. - Status —
ActiveorDisabled. Disabled users cannot sign in and have all sessions revoked. - Last active — relative time since the user's last request (refreshed at most once every 20 seconds by the session middleware).
A search box above the table filters by name or email as you type.
Click Manage on any row to open the user-manage modal.
The user-manage modal
The modal has up to four tabs:
- Profile & Access — display name override (with a name lock and an avatar lock), role assignment, account status, and per-user rate limit override.
- Extensions & Data — enable or disable individual extensions for this user, set per-user capability overrides (Analysis, Jira writes, Confluence writes, and AI model access), set per-connection database access, and run three per-user data actions: wipe memory, delete all conversations, and export all data.
- Usage — links out to the user's full billing profile at
/admin/usage/<userId>(full-width charts and tables live there). This tab only appears if your role grantscanViewUsage. - Agents — every scheduled agent this user owns, plus the per-user agent governance controls (lock creation, allowed tools mask).
Changing a user's role
In the Profile & Access tab, pick a new role from the Role dropdown and save. The change is audited as user.role_assigned with the from-role and to-role IDs.
Two safety rails apply:
- Last-admin guard. If demoting this user would leave the organization with zero admins (any user whose role grants
canAccessAdminand whose account is active), the request is rejected withCannot remove the last admin — promote another user to admin first. - Extension sweep. If the new role allows fewer extensions than the old one, any in-flight OAuth tokens for now-disallowed extensions are revoked on the next request. Jira and Confluence share one Atlassian connection, so that token survives as long as either product is still allowed.
The user's session permissions rehydrate within roughly 30 seconds. To make the change land immediately, use Force sign out (all devices) in the same modal.
Setting a per-user rate limit
The rate limit input accepts a number per hour and a unit toggle of chats or tokens. Leave it blank to inherit the cascade. The full cascade is:
user.rate_limit_override → role.default_rate_limit → org.default_rate_limit → env CHAT_RATE_LIMIT_PER_HOUR → 60 chats
See Rate limits and quotas for the complete cascade and what users see when capped.
Per-user capability overrides
The Extensions & Data tab carries per-user overrides that narrow what a single person can do below their role and the org default.
- Extensions — toggle each integration (SQL Server, Outlook, OneDrive, SharePoint, Microsoft Teams, Web search, Jira, Confluence) on or off for this user. A disabled extension disappears everywhere in their UI, and for the Microsoft extensions turning one off revokes its OAuth tokens on the user's next request. Jira and Confluence are governed separately but ride one Atlassian connection: turning either off withholds that product's tools from this user's chat and from the agents they own, without disconnecting anything. Their stored Atlassian token is dropped only when neither Jira nor Confluence is allowed for them. See Atlassian extensions.
- Analysis —
Inherit role / org,Allowed, orDenied. The effective value resolves user → role → org default, so this control can grant or deny sandboxed code execution for one user regardless of their role. See Analysis. - Jira writes —
Inherit role / org,Allowed (if the org allows), orDenied. See Restricting one user's Jira writes below — the semantics differ from the Analysis control. - Confluence writes — the same three values, resolved the same way but entirely independently of Jira. A member can be free to file issues and blocked from creating pages, or the reverse. See Restricting one user's Confluence writes below.
- AI models — restrict which models this user can pick.
- Database access — set a per-connection permission tier (and the per-connection "auto-approve writes" flag) for each org SQL connection. Leave a connection blank to inherit the role default.
Restricting one user's Jira writes
Jira writes looks like the Analysis control but does not behave like it. Analysis resolves user → role → org and the most specific level wins, so Allowed there can grant. Jira writes is an intersection: it can only narrow the organization's Let Strata create issues and comment toggle, in the Jira section of the Atlassian tab of Organization settings.
- Allowed (if the org allows) grants nothing. It means "this user is not narrowed". With the organization's writes off, a user set to Allowed still cannot write — which is what the label is warning you about.
- Denied is the only value here that changes anything: Strata never creates an issue or posts a comment on this user's behalf, in chat, in the agents they own, in Teams, or through an API key bound to them.
- Inherit role / org behaves exactly like Allowed.
The role's own Jira writes capability (see Roles and permissions) narrows in the same way, and a Denied at either layer is enough. If an admin has turned on Apply to everyone, with no exceptions for Jira on the Atlassian extension page, this control stops applying entirely and the org toggle is the whole answer.
The help text under the picker shows the resolved answer — Currently enabled for this user or Currently disabled for this user — and rewrites itself as soon as you change the selection, so you can confirm the outcome without reasoning through the layers. Saving is audited as user.jira_write_access_changed with the before and after. The change takes effect on the next request; no session refresh is needed.
If Strata cannot resolve the value — a database error, or a user with no matching record — writes are off. The control fails closed.
The same values are readable and settable through GET and PATCH /api/admin/users/:userId/jira-write-access (both require canManageUsers). The PATCH body takes jira_allow_writes_override as "inherit", "allow", or "deny"; the response returns the stored override alongside the resolved effective answer.
Restricting one user's Confluence writes
Confluence writes behaves identically — an intersection that can only narrow, failing closed, with its own per-product Apply to everyone, with no exceptions lock — but it resolves against the organization's Let Strata create and edit pages toggle in the Confluence group of the Atlassian extension page, and against the role's own Confluence writes capability. Nothing crosses over: denying a user Jira writes leaves their Confluence writes untouched, and denying Confluence writes leaves Jira alone. Saving is audited as user.confluence_write_access_changed.
Despite that toggle's wording, Strata never edits a page that already exists. The only writes it can make are creating a new page and adding a comment, so Denied here is what stops a member's chat or agents from doing either.
Restricting a user's AI models
Strata runs a DB-driven Model Catalog that Kronisys curates centrally; each organization enables the subset it wants from Org Settings → Models → Model Catalog. See Organization settings. The models a user can actually pick are the intersection of what the org has enabled, what their role allows, and this per-user override.
In Extensions & Data → AI models, you see a checkbox per org-enabled model. The effective rule is:
- Leave everything checked (or check the full set) — the user inherits the org/role models. No override is stored.
- Uncheck one or more models — the user is limited to the checked set, which can be narrower than the org or their role, but never broader.
- Unchecking every box also resolves to inherit — Strata never locks a user out of every model.
Saving is audited as user.model_access_changed with the before/after model lists. The change applies to chat, agents, the Microsoft Teams bot, and API keys — disabling a model anywhere is enforced everywhere. (Voice mode runs on a fixed realtime model the org deploys separately, so the chat-model allowlist doesn't gate it.)
NoteThis is an allowlist that only narrows access. To make a model available in the first place, enable it for the whole organization in the Model Catalog; to widen a role, edit the role's allowed models under Roles and permissions.
Per-user data actions
Three buttons in the Extensions & Data tab cover the most common privacy and offboarding workflows:
- Wipe memory. Clears the user's persistent memory entries and free-text memory blob. Audited as
user.memory_wiped. The user keeps their conversations, settings, and connections. - Delete all conversations. Hard-deletes every conversation and every message belonging to the user. Artifacts cascade. Activity log entries are preserved for org analytics. Audited as
user.conversations_deletedwith the deleted count. - Export all data. Returns a JSON file named
user-export-<first-8-of-uuid>.jsoncontaining the user's conversations, messages, and settings. Downloads directly to your browser. Because the file carries full message content, this action requires thecanManageCompliancepermission and the org's member-chat-oversight setting must be on — otherwise the request is rejected with a 403.
The button labeled Delete user permanently at the bottom of the modal removes the user row plus every related record. See "Deleting a user" below.
Promoting and demoting users
The system uses case-insensitive UUID comparison everywhere the actor matches a target — SQL Server stores UUIDs uppercase while randomUUID() and URL parameters produce lowercase. This matters because:
- You cannot delete your own user. The check
String(userId).toLowerCase() === String(actor.userId).toLowerCase()blocks the request and returnsYou can't delete your own account. - When you demote yourself from admin, the last-admin guard protects you from locking the org out.
- A self-revoke session ("Sign me out" on your own session row) skips the cross-org guard since you are the target.
Groups
A person can also belong to any number of groups — Engineering, On-Call — which label them without granting anything. Groups appear as chips on the user row, can be assigned from the row or in bulk, and the roster can be filtered by them. A group is not a role: see A group is not a role.
Bulk actions
Select one or more user rows with the checkboxes; a bulk action bar appears at the bottom of the page with a > toggle that opens these actions:
- Activate — set
is_active=1for the selected users. - Disable — set
is_active=0; revokes all sessions immediately. - Change role — opens a single-select dialog of every role in your org; applies that role to every selected user (last-admin guard still applies per user).
- Export data — emails you a ZIP of conversations, messages, settings, and analytics for every selected user, one folder per user. Capped at 200 users per request. Download link expires in 24 hours. Requires the
canManageCompliancepermission, and the org's member-chat-oversight setting must be on (the export discloses full message content). - Delete — hard-deletes the selected users with a confirmation dialog. Last-admin guard applies; self-delete is blocked.
The Users page bulk endpoint is rate-limited to 20 requests per 5 minutes per admin to prevent UUID enumeration. Hitting the cap returns Too many bulk requests. Please wait a few minutes before trying again. with a Retry-After: 300 header.
The Activate, Disable, Change role, and Delete actions run through the bulk endpoint, return {successCount, errorCount, errors}, and are audited as user.bulk_<action> with the per-user outcomes. Export data is handled by a separate endpoint that queues a background job (returning {ok, message, count}) and is audited as admin.users_exported.
Deleting a user
Use Delete user permanently in the Manage modal, or the bulk Delete action, when you need to remove someone for good.
A delete hard-removes the user row plus:
- Sessions
- Extension permissions and OAuth tokens
- Database access rows
- User settings
- Conversations and messages (artifacts cascade)
- Personal database connections
- Personal files, skills, and deployed agents (agents can be transferred to another active member instead of deleted)
Activity-log entries are anonymized rather than removed — the user link and PII columns (the prompt text, response preview, prompt embedding, conversation link, IP) are nulled, while the metered columns the org needs (org_id, model_id, token counts, cost, source, timestamps) are kept, so org-wide usage/cost totals stay correct.
Audit log entries actioned by the deleted user are preserved (other admins still need to see "user X was disabled by deleted-user Y" history). Org-level connections and shared resources are untouched.
For GDPR or HR offboarding workflows that need a record of the user's data, run Export all data before deleting.
What can go wrong
| Error | What it means |
|---|---|
Admin access required | Your role does not grant canAccessAdmin. |
Permission required: canManageUsers | Your admin role can view the page but cannot make changes. |
Cannot remove the last admin — promote another user to admin first. | You tried to demote, disable, or delete the only remaining active admin. |
You can't delete your own account. | Self-delete is blocked. Have another admin do it. |
Not found (404) | The user UUID does not exist in your org. Usually a stale link to a deleted user. |
Too many bulk requests. Please wait a few minutes before trying again. | More than 20 bulk requests in 5 minutes from your account. |
Max 200 user_ids per export. Run in batches. | Split the export into multiple smaller batches. |
Action failed for this user (in a bulk result) | A real error happened for that specific user; the rest of the batch continued. Server logs have the real reason. |
See Audit log for the trail of every user change, Sessions for force-sign-out, and Roles and permissions for the role model.
Related
- Roles and permissions
- Organization settings — the Model Catalog and org-wide allowed models
- Active sessions
- Per-user agent governance
- Atlassian extensions — the three layers that decide who may write to Jira and Confluence