Files
SnapOtter/apps/docs/guide/users-roles.md
T
SnapOtterandGitHub 1f8a42e548 fix: enforce role authority for user management (#616)
Centralize role-authority enforcement across user management, role management, configuration import, SCIM, GDPR, and MFA mutations. Add regression coverage for delegated custom roles and protect higher-privilege accounts from reset, deletion, or takeover.
2026-07-22 01:23:15 +08:00

11 KiB

description
description
Manage users, built-in and custom roles, permissions, API keys, teams, sessions, and the audit log in SnapOtter.

Users, Roles & Permissions

SnapOtter ships three built-in roles, 17 granular permissions, and support for custom roles with optional per-tool access control. This page covers the full authorization model, API key scoping, team management, and audit logging.

::: tip Related pages OIDC / SSO | SAML SSO | SCIM Provisioning | Security & Hardening :::

Users

Creating users

Admins can create users through the admin panel or the POST /api/auth/register endpoint. Each user has a username, role, team assignment, and an optional email address.

Default admin

On first startup SnapOtter creates a default admin account. The credentials come from environment variables:

Variable Default Description
DEFAULT_USERNAME admin Username for the initial admin account
DEFAULT_PASSWORD admin Password for the initial admin account

The default admin is required to change their password on first login.

Authentication providers

Users can authenticate through several methods:

  • Local - username and password stored in the SnapOtter database
  • OIDC - any OpenID Connect provider (see OIDC / SSO)
  • SAML - SAML 2.0 identity providers (see SAML SSO)
  • SCIM - automated provisioning from an identity provider (see SCIM Provisioning)

Disabling authentication

Set AUTH_ENABLED=false to disable authentication entirely. In this mode a synthetic anonymous user with the admin role is used for all requests. No login is required.

::: warning Disabling authentication grants full admin access to anyone who can reach the instance. Only use this in trusted environments. :::

Built-in roles

SnapOtter includes three built-in roles. They cannot be modified or deleted.

Admin

All 17 permissions. Full control over the instance.

tools:use files:own files:all apikeys:own apikeys:all pipelines:own pipelines:all settings:read settings:write users:manage teams:manage features:manage system:health audit:read compliance:manage webhooks:manage security:manage

Editor

7 permissions. Can use all tools and manage all files and pipelines, but cannot access admin functions.

tools:use files:own files:all apikeys:own pipelines:own pipelines:all settings:read

User

5 permissions. Can use tools and manage their own resources.

tools:use files:own apikeys:own pipelines:own settings:read

Permissions reference

Permission Description
tools:use Use any processing tool
files:own View and manage own files
files:all View and manage all users' files
apikeys:own Create and manage own API keys
apikeys:all View all users' API keys
pipelines:own Create and manage own pipelines
pipelines:all View and manage all users' pipelines
settings:read View instance settings
settings:write Modify instance settings
users:manage Create and manage user accounts within the actor's authority boundary
teams:manage Create, update, and delete teams
features:manage Install and manage AI feature bundles
system:health Access health and readiness endpoints
audit:read View the audit log and list roles
compliance:manage Manage GDPR lifecycle and compliance features; destructive user operations remain authority-bounded
webhooks:manage Configure outbound webhooks
security:manage Manage security settings (IP allowlist, SSO enforcement)

Custom roles

Admins with the security:manage permission can create custom roles through the admin panel or the roles API. Listing roles requires audit:read.

Creating a custom role

curl -X POST http://localhost:1349/api/v1/roles \
  -H "Authorization: Bearer si_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "reviewer",
    "description": "Can use tools and view all files",
    "permissions": ["tools:use", "files:own", "files:all", "settings:read"]
  }'

Role names must be 2-30 characters, lowercase alphanumeric with hyphens and underscores.

Delegated administration boundaries

All 17 permissions can be delegated through custom roles, but an administrative permission does not make that role equivalent to the built-in admin role. User mutations authorized by users:manage, destructive operations authorized by compliance:manage, and custom-role management authorized by security:manage are bounded by the actor's current authority:

  • Built-in roles follow admin > editor > user; custom roles are below built-in roles.
  • The target's permissions must be contained by the actor's effective permissions. A scoped API key therefore cannot exercise permissions omitted from its scope.
  • A target role's tool access must be contained by the actor's own tool access.
  • A disabled account is checked against its original role when that role is recorded as disabled:<original-role>.
  • Deleting a custom role also requires authority to assign the built-in user fallback; disabled members remain disabled as disabled:user.

Global credentials and configuration are stricter: issuing or revoking the SCIM token and importing instance configuration require the built-in admin role with complete effective admin authority.

Tool-level permissions

Custom roles can optionally restrict which tools users may access. Two modes are available:

Mode Behavior License requirement
category Restrict by modality (image, video, audio, document, file) None (free)
tool Restrict by individual tool ID Requires the per_tool_permissions enterprise feature

When tool mode is set but the enterprise feature is not available, SnapOtter degrades gracefully and allows access to all tools.

{
  "name": "image-only",
  "permissions": ["tools:use", "files:own"],
  "toolPermissions": {
    "mode": "category",
    "allowed": ["image"]
  }
}

Deleting a custom role

When a custom role is deleted, all users assigned to it are automatically reassigned to the user role.

Teams

Teams group users for storage and retention management. A Default team is created on first startup.

Field Type Description
name string Unique team name (1-50 characters)
storageQuota number Per-team storage limit in bytes (works without enterprise)
retentionHours number Auto-delete outputs after this many hours (requires team_retention_overrides, enterprise)
legalHold boolean Prevent automatic deletion of team members' files (requires legal_hold, enterprise)

::: info The Default team cannot be deleted. Teams that still have members cannot be deleted. Reassign members first. :::

API keys

Users can generate API keys for programmatic access. Each key uses the si_ prefix and is shown only once at creation time.

Scoped permissions

API keys can optionally carry a permissions array. When set, the effective permissions for a request are the intersection of the user's role permissions and the key's scoped permissions. This means an API key can never escalate beyond the user's own permissions.

curl -X POST http://localhost:1349/api/v1/api-keys \
  -H "Authorization: Bearer si_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "CI pipeline key",
    "permissions": ["tools:use", "files:own"],
    "expiresAt": "2027-01-01T00:00:00Z"
  }'

Expiration

Keys accept an optional expiresAt timestamp. Expired keys are rejected at authentication time.

Audit log

SnapOtter records security-relevant events in a structured audit log stored in the audit_log database table.

Viewing the audit log

GET /api/v1/audit-log?page=1&limit=50&action=LOGIN_FAILED&from=2026-01-01T00:00:00Z&to=2026-12-31T23:59:59Z

Requires the audit:read permission. Supports pagination (page, limit) and filters (action, ip, from, to).

Tool operation auditing

::: warning TOOL_EXECUTED events are not logged by default. They are opt-in through either of two paths:

  1. Set the auditToolOperations admin setting to true.
  2. Hold an active license with the audit_export feature (available on both team and enterprise plans).

Without one of these, individual tool executions are not recorded in the audit log. :::

Exporting

GET /api/v1/enterprise/audit/export?format=csv&from=2026-01-01T00:00:00Z

Requires the audit:read permission and the audit_export enterprise feature (available on both team and enterprise plans). Supports CSV and JSON formats, filtered by action, actorId, targetType, targetId, from, and to.

Tamper-resistant signing

When enabled, each audit log entry is signed with an HMAC derived from DATA_ENCRYPTION_KEY. This requires:

  1. Setting DATA_ENCRYPTION_KEY in your environment.
  2. Enabling the tamperResistantAudit admin setting.
  3. An enterprise license with the tamper_resistant_audit feature.

Retention

Set AUDIT_RETENTION_DAYS to automatically purge old entries. The default is 0, which means entries are kept indefinitely.

Event reference

Event Category
LOGIN_SUCCESS, LOGIN_FAILED Authentication
OIDC_LOGIN_SUCCESS, OIDC_LOGIN_FAILED Authentication
SAML_LOGIN_SUCCESS, SAML_LOGIN_FAILED Authentication
LOGOUT Authentication
USER_CREATED, USER_UPDATED, USER_DELETED User management
PASSWORD_CHANGED, PASSWORD_RESET User management
MFA_ENROLLED, MFA_DISABLED, MFA_VERIFIED, MFA_VERIFY_FAILED MFA
MFA_CHALLENGE_ISSUED, MFA_RECOVERY_USED, MFA_RESET MFA
ROLE_CREATED, ROLE_UPDATED, ROLE_DELETED Roles
API_KEY_CREATED, API_KEY_DELETED API keys
SETTINGS_UPDATED, IP_ALLOWLIST_UPDATED Settings
FILE_UPLOADED, FILE_DELETED Files
TOOL_EXECUTED Tools (opt-in)
SCIM_USER_PROVISIONED, SCIM_USER_UPDATED, SCIM_USER_DEPROVISIONED SCIM
SCIM_GROUP_SYNCED SCIM
LEGAL_HOLD_APPLIED, LEGAL_HOLD_RELEASED Compliance
GDPR_EXPORT_INITIATED, GDPR_USER_PURGED, GDPR_TEAM_PURGED Compliance
CONFIG_EXPORTED, CONFIG_IMPORTED Configuration

Session management

Sessions are cookie-based, controlled by SESSION_DURATION_HOURS (default: 168 hours / 7 days).

Role changes invalidate sessions

When an admin changes a user's role, all of that user's active sessions are deleted. The user must log in again to pick up their new permissions.

Safety guards

  • Last-admin protection: the last remaining admin cannot be demoted to a lower role. The API returns an error if you try.
  • Self-delete prevention: admins cannot delete their own account through the API.