Server security & auth admin: session login/logout, active sessions, and user/group/API-token
management — over ArcadeDB's HTTP admin surface. Reads (users/groups/api_tokens/sessions)
use the read-only REST endpoints; mutations (create_user/drop_user) use server commands (the
REST paths are read-only — POST /server/users → 400). Tenant-blind.
create_user/2 is the one place a caller VALUE (the password) reaches a statement: server commands
cannot bind params (probed), so the user spec is Jason.encoded into create user <json> — the
JSON backslash-escaping round-trips exactly against ArcadeDB's create user lexer (live-verified).
The encode uses the NON-raising Jason.encode/1: a non-UTF8 binary password passes the is_binary
guard but would make Jason.encode! raise a Jason.EncodeError that renders the raw bytes, so an
unencodable spec is rejected value-free as {:error, :invalid_user_spec} (the Jason error, which
holds the bytes, is discarded) before any wire call. The password NEVER enters an error, log, or
telemetry line (the server error is name-only; arcadic only ever emits valid JSON; Arcadic.Error
quarantines detail; the admin span is value-free).
Summary
Functions
List server API tokens (GET /api/v1/server/api-tokens).
Create a server user from %{name:, password:, databases: %{db => [roles]}} (databases optional).
name is Identifier-validated; the spec is Jason.encoded into the command. The password is never
echoed (Rule 3): an unencodable spec (e.g. a non-UTF8 binary) is rejected value-free as
{:error, :invalid_user_spec}. Returns :ok or a typed error.
Drop a server user. Validates name.
The server security-groups map (GET /api/v1/server/groups).
Mint a session token from the conn's credentials (POST /api/v1/login).
Revoke the current session (POST /api/v1/logout).
List active sessions (GET /api/v1/sessions). Rows carry caller-owned tokens — do not log them.
List server users (GET /api/v1/server/users).
Functions
@spec api_tokens(Arcadic.Conn.t()) :: {:ok, [map()]} | {:error, Exception.t()}
List server API tokens (GET /api/v1/server/api-tokens).
@spec api_tokens!(Arcadic.Conn.t()) :: [map()]
@spec create_user(Arcadic.Conn.t(), map()) :: :ok | {:error, atom() | Exception.t()}
Create a server user from %{name:, password:, databases: %{db => [roles]}} (databases optional).
name is Identifier-validated; the spec is Jason.encoded into the command. The password is never
echoed (Rule 3): an unencodable spec (e.g. a non-UTF8 binary) is rejected value-free as
{:error, :invalid_user_spec}. Returns :ok or a typed error.
@spec create_user!(Arcadic.Conn.t(), map()) :: :ok
@spec drop_user(Arcadic.Conn.t(), String.t()) :: :ok | {:error, atom() | Exception.t()}
Drop a server user. Validates name.
@spec drop_user!(Arcadic.Conn.t(), String.t()) :: :ok
@spec groups(Arcadic.Conn.t()) :: {:ok, map()} | {:error, Exception.t()}
The server security-groups map (GET /api/v1/server/groups).
@spec groups!(Arcadic.Conn.t()) :: map()
@spec login(Arcadic.Conn.t()) :: {:ok, String.t()} | {:error, Exception.t()}
Mint a session token from the conn's credentials (POST /api/v1/login).
@spec login!(Arcadic.Conn.t()) :: String.t()
@spec logout(Arcadic.Conn.t()) :: :ok | {:error, Exception.t()}
Revoke the current session (POST /api/v1/logout).
@spec logout!(Arcadic.Conn.t()) :: :ok
@spec sessions(Arcadic.Conn.t()) :: {:ok, [map()]} | {:error, Exception.t()}
List active sessions (GET /api/v1/sessions). Rows carry caller-owned tokens — do not log them.
@spec sessions!(Arcadic.Conn.t()) :: [map()]
@spec users(Arcadic.Conn.t()) :: {:ok, [map()]} | {:error, Exception.t()}
List server users (GET /api/v1/server/users).
@spec users!(Arcadic.Conn.t()) :: [map()]