Omniscio documentation
Browse all documentation
  1. Getting Started13
  2. Sessions & Agents115
  3. Inbox & Notifications59
  4. Projects & Tasks95
  5. Automation & Scheduling75
  6. Knowledge & Memory26
  7. AI Features60
  8. Integrations100
  9. Plugins & Marketplace33
  10. Cloud & Teams56
  11. Settings & Customization58
  12. Account & Billing28
  13. Troubleshooting84
  14. CLI & API Reference22
  15. Legal & Policies4
  16. Uncategorised22

User Management

An owner and admin console for running an Omniscio organization: inviting people, reviewing requests to join, setting roles and subscription tiers, disabling or deleting accounts, and managing Team Chat workspace membership. It belongs to the optional cloud identity layer, so it is absent on a single-user install, and the desktop console ships only in internal builds.

What it is

User Management is an owner/admin-only admin console for running an Omniscio organization — inviting people, reviewing who's asking to join, setting each person's role and subscription tier, disabling or deleting accounts, and managing workspace membership for Team Chat.

Read this caveat first, because it changes who this page is even for: User Management is part of Omniscio's optional cloud identity layer ("Global Auth"), which is off on the vast majority of installs. On a normal single-user install there's no organization, no other users, and no reason for this panel — so it doesn't appear at all. The Settings row itself shows for any signed-in user once the Global Auth sign-in gate is turned on, but the full admin console described on this page — the Users / Access Requests roster, invites, role and tier changes — only renders for a global owner or admin. A plain member sees the same row labeled Workspaces and opening only the self-serve workspace surface (list + switcher + Create), not this console. If you're an individual user wondering where the admin console is, the honest answer is: it's an administrator feature for multi-person orgs, and it's almost certainly not relevant to you.

For the admins it is for, it's the one place to manage the whole membership of your org from inside Omniscio.

Where to find it

Where it lives: Settings → User Management (grouped under "Accounts & AI", or under a "Team & Admin" group in the newer settings layout). The nav row renders for every signed-in user, but its label and contents are role-shaped: global owner/admin staff see the full User Management console described here (three tabs — Users, Access Requests, and Workspace — with Invite User and Bulk Invite buttons in the header); a plain member sees the same row labeled Workspaces, opening the workspace surface only (their workspace list + switcher + Create, no tabs and no invite buttons — see Self-serve workspaces below). Signed-out, the row is hidden.

How it behaves

How to use it

  • Invite one person. Click Invite User → enter their Email (required) and optional Display Name, pick a Role (Owner / Admin / Member / Trial) and a Tier (Enterprise / Pro / Free) → Invite. This pre-creates their account so they skip the request-to-join step when they first sign in, and sends them an invite email (from invites@amcmailbox.com, linking the download page). The invitee then appears in the Users tab as a labeled Invited row until they first sign in.
  • Invite many at once. Click Bulk Invite → paste a list of emails separated by commas, spaces, or new lines → Invite (N). Re-running is safe: already-invited addresses are skipped, and you get a per-email summary of invited / skipped / errored. Each successfully-invited address also gets the invite email.
  • See and revoke pending invites. An invited-but-not-yet-signed-in person shows as an Invited row (amber pill, em-dash last-login, amber status dot; there's also an "Invited" option in the Status filter). Its ⋮ menu has exactly one action — Revoke Invite — which deletes the invite and any pending access request from the same email. Role/tier/disable/delete are deliberately unavailable on a pending row.
  • Approve or deny a request to join. The Access Requests tab (with an amber count badge when any are pending) lists each request as a card — name, email, "Requested X ago" — with Approve and Deny. Approve pre-creates the user (member/free), clears the request, and emails them that their access was approved; Deny just clears it.
  • Change a role or tier, or disable/remove someone. On the Users tab, filter by search / role / tier / status, then use a row's ⋮ menu: Change Role ▸, Change Tier ▸, Enable / Disable Account, or Remove User (confirm-gated). Every one of these is disabled on your own row — you can't change, disable, or remove yourself (last-owner and self-lockout protection). The roster is paginated — 50 users per page with Prev / Next controls below the table — and the search box, the Role / Tier / Status filters, and column sorting are all applied by the server (search still matches anywhere in the name or email), so you page through matches rather than filtering a single fully-loaded list.
  • Manage workspace membership. The Workspace tab lists your org's Team Chat members and lets you assign or unassign users to the org, with an org role of org_admin or member. A member still pending an invite shows an Invited pill (instead of a role) and its per-row action reads Revoke invite rather than Remove; every row action (Make admin / Make member / Remove / Revoke invite) shows a busy state while the change applies so it can't be double-fired.
  • Role and org changes reach the affected person automatically — no re-login. When you change someone's role/tier or their workspace assignment, their running app picks the change up on its own: the server re-mints their identity claims, and their app broadcasts the new identity the next time it silently refreshes its session token (a window reload triggers an immediate re-check; a long-idle app catches up on its periodic re-verification, at most a few hours). Only Disable Account forcibly ends their session. Changing a user's global role also never demotes a workspace they own — a self-serve workspace creator stays its owner.

For agents

How it works

The visibility rule you see is only cosmetic. The nav row is drawn for every signed-in user in Settings-section-groups.tsx, with globalAuthRole === 'owner' || globalAuthRole === 'admin' choosing the User Management label and the full console versus the member-facing Workspaces label and workspace-only surface. That role check controls what the menu entry says and shows — it is not the security boundary.

The real boundary is server-side and cryptographic. Every operation in the panel runs a fast local assertCaller* pre-check (profile-authz.ts) and then routes the read/write through a token-verifying Cloud Function (globalAuthAdmin / globalAuthProfile, project the shares backend runs on) that re-verifies authorization on the server using the caller's Firebase ID-token claims. assertCaller reads role/tier from the cryptographically-verified token claims — not the machine-editable local cache — so a tampered client can't forge its way past it. Which pre-check runs depends on the tab, and the two are deliberately different:

  • Global-admin ops (the Users and Access Requests tabs — invite, bulk-invite, change role/tier, disable, remove) call assertCallerIsAdmin(), asserting the manage_users capability: minimum role admin, full stop.
  • Workspace-tab org ops (listOrgMembers, assignUserOrg, bulkInviteToOrg in admin-operations.ts) call assertCallerCanManageOrgMembers(), asserting manage_org_members: minimum role admin OR orgAdminGrants — a caller whose verified claim carries orgRole === 'org_admin' passes regardless of their global role. That is the point: it is how a workspace owner/admin manages their own org's roster without being global staff (see the org-admin scoped panel below). So a plain global member who is an org-admin can use the Workspace tab, and cannot touch anything on the Users tab.

Both capabilities are defined in the entitlements policy (entitlements.ts). The admin operations live in admin-user-operations.ts (the global-admin ops — off-shipped, see the next paragraph) alongside the org-scoped roster ops in admin-operations.ts; the IPC surface is global-auth-handlers.ts (the global-admin handlers are compile-time-gated); the renderer state is user-admin-store.ts for the admin console and user-management-store.ts for the shipping workspace/org surface.

The desktop admin console is compile-time OFF-SHIPPED from the packaged build (2026-07-21). Omniscio is an Electron app, and a shipped build is trivially asar extract-able — so a runtime role gate hides the console from a casual user but is not confidentiality. The whole owner/admin console (the Users / Access Requests roster, the global Invite User / Bulk Invite tools, role/tier changes, the all-orgs list, the Team-Chat add-members picker, and the invite-only mode toggle) is now built behind an INTERNAL_ONLY guard and tree-shaken OUT of the production bundle — it renders only in internal/dev builds. Staff manage users from the separate admin webapp (firebase/admin-dashboard) instead. What still ships to every customer is the org-scoped workspace surface (a plain member's Workspaces list + switcher + Create; an org-admin's own-workspace roster). Server-side authz is unchanged — the strip removes the desktop tooling, not the security boundary. Full detail: offship-admin-surfaces-contract.md.

The role/tier model (source of truth: paid-offering.ts for the tier/limit values, re-exported by entitlements.ts, which holds the roles/policy):

  • Roles, least → most privileged: trial < member < admin < owner.
  • Tiers, low → high: free < pro < team < enterprise. (team is the per-seat collaboration rung, above pro. There is no starter tier — it was retired; if you see one in an older doc or a stale admin-granted value, it is not in TIER_RANK.)
  • Org role (within a Team Chat workspace): org_admin or member.
  • Unknown/corrupt values defensively coerce to the least privilege (member / free), so a bad stored value can never widen access.

Removing a user is a "kick", by design (2026-07-17 decision). It removes their profile document but not their underlying Firebase Auth login — the person can sign in again and start fresh (or re-request access when invite-only is on). The confirm dialog says exactly this and points to Disable Account as the tool that actually blocks access. Relatedly, the per-request disabled check fails closed: if the server can't verify whether an account is disabled (a database blip), the request is refused with a retry message rather than letting a possibly-disabled account act. And the whole console is meaningful only when the Global Auth gate is active: when it's off (the default), Omniscio treats the local user as the sole "operator" and there simply are no other users to manage.

The Users list is capped server-side (5,000 rows). Past the cap, the tab shows a warning banner ("Showing the first 5,000 users…") instead of silently truncating.

One clarification worth flagging: the tier here (free/pro/team/enterprise, your Omniscio subscription level) is a different concept from the Claude account plan tier (Max/Pro/Free) used to pick a session's default model — see the note in account-tier-model-defaults.md. Same word, unrelated setting.

Self-serve workspaces

A newer layer that lets a customer run their own workspace instead of relying on staff to provision one. It is registered as the self-serve-workspaces feature (settingKey: selfServeWorkspacesEnabled) and was shipped on 2026-07-19 — it shows for every eligible signed-in user, no Lab toggle needed. The whole thing is all-Firebase by an explicit owner decision (2026-07-17), which is why the membership subcollection — not the user profile — is the source of truth for who belongs to a workspace. Full engineering detail: self-serve-workspaces-contract.md.

Five things it adds:

  • Create a workspace (paid-gated). Any signed-in, email-verified user on a paid subscription tier (pro / team / enterprise — the gate's paidTiers default, matching PAID_TIER_ROLES in paid-offering.ts) can create their own workspace and become its owner — a user can belong to several workspaces at once. The Create workspace button sits in the header of the section (the Workspaces section for a plain member, the User Management header for staff) alongside the workspace switcher, and on the empty state when you belong to none. A free-tier user is refused with a typed upgrade_required code and routed to the Plan & Usage screen (Settings → Accounts & AI); other typed refusals are email_unverified, workspace_limit (you've hit your plan's owned-workspace cap, default 3), invalid_name (names are 2–50 characters), and disabled (creation turned off in config). Every refusal is humanized — no raw Firebase error reaches the screen.
  • Switch the active workspace. A workspace switcher (a dropdown plus a "+" create button) in the User Management header lists every workspace you belong to and marks the active one. Switching re-mints your identity token for the new workspace and reloads the scoped data. Switching or creating is self-initiated, so it never signs you out of your other devices (no token revoke).
  • Leave a workspace. A plain member can leave a workspace they belong to (but don't own) directly from Settings → Workspaces — each row carries a confirm-gated Leave action, so leaving no longer requires hunting through the Team-Chat rail. Leaving the active workspace switches you to another one first so you're never stranded; the sole owner is server-refused (owners delete the workspace instead).
  • Upgrade path (was the "Pricing screen"). The standalone mock Settings → Pricing section was RETIRED on 2026-08-18 in the money-surface consolidation. A free-tier user who tries to create a workspace is now routed to the real Settings → Accounts & AI → Plan & Usage storefront — one place to compare plans, upgrade, buy credit, and manage billing (see plan-billing.md). The backend pricing config (config/pricing) and its getPricingConfig/loadPricing accessors are kept but dormant.
  • Org-admin scoped panel. A workspace owner or admin (a per-workspace role, distinct from the global owner/admin staff role) gets a scoped view of User Management: they can manage their own workspace's roster (invite, remove, change the workspace role) but not global roles, tiers, or other orgs. The full all-users view stays super-admin-only. This is the manage_org_members capability — see entitlements-contract.md.

Under the hood the membership doc at organizations/{orgId}/members/{uid} is the authority (byte-exact {uid, role, displayName, photoURL, joinedAt, status}); users/{uid}.organizationId + orgRole are just the "active workspace" projection that feeds the verified claims. Invites and domain auto-join add a membership rather than moving you between orgs. A one-time admin backfill (backfillOrgMembers) promotes every already-assigned user into their org's members subcollection.

Caveats

  • The full admin console is owner/admin-only — a plain member sees only the Workspaces surface (their workspace list + switcher + Create), never the Users / Access Requests roster or invite tools. The whole section stays invisible on a solo/single-user install where the Global Auth gate is off, and to anyone signed out. This is the headline caveat, not a footnote.
  • The desktop admin console is dev/internal-only — it is compile-time OFF-SHIPPED from the production build (Electron source is extractable, so the code is removed, not merely hidden); global staff manage users from the admin webapp, and only the org-scoped workspace surface ships to customers. See offship-admin-surfaces-contract.md.
  • Cloud-backed (Firebase Auth + Cloud Functions). Not a local-only feature; it does nothing without the Global Auth gate turned on.
  • Not an in-development / Lab-gated feature — it's a normal shipped section gated purely by role, not by a feature flag.
  • Self-protection is enforced both in the UI and on the server (you can't remove your own access; last-owner protection applies).

Related

  • team-chat.md — the closest relative: it uses the same Global Auth identity and organization model, and the Workspace tab + Bulk Invite feed its membership
  • account-tier-model-defaults.md — the other "tier" (Claude account plan → default model), not to be confused with the subscription tiers here
  • consumer-terms-gate.md — the Terms/consent gate that pairs with the Global Auth sign-in flow
  • Omniscio’s unreleased-feature (“Lab”) gate — the gating mechanism the self-serve workspaces layer rode while in development (now shipped)

Last verified 2026-09-28