# Manage Logins

Task-oriented recipes. Each section assumes you already have `splam` installed and running. See the [Tutorial](tutorial-getting-started.md) if not.


# Manage login accounts

Add or update an account:

``` bash
splam-users add <username>
```

List existing accounts and their roles:

``` bash
splam-users list
```


# Give an account a role

Every account has one of two roles:

| Role | Can do |
|----|----|
| `admin` | Everything: Start/Stop/Restart, Configure, and all read-only tabs |
| `auditor` | Read-only: Status, Tasks, Doc, Logs, and Audit Trail |

`admin` is the default, so `splam-users add <username>` with no `--role` creates an `admin` account. Users can add a read-only account with:

``` bash
splam-users add qa-reviewer --role auditor
```

An auditor sees no **Actions** tab and no **Configure** button. This role is also enforced server-side, so an action submitted by a hand-crafted client is rejected and recorded in the audit trail with the result `rejected: role not permitted`.

Change an existing account's role by adding it again with the role you want (`add` replaces the whole record, so you'll be prompted for the password again).


# Unlock an account

After five consecutive failed logins the account is refused for 15 minutes (even if the correct password is then supplied). The login form shows the remaining time, and each attempt is recorded in the audit trail.

Users can adjust the number of failed login attempts and the lockout duration with `SPLAM_MAX_FAILED_LOGINS` and `SPLAM_LOCKOUT_SECONDS`. Lockout state is held in memory by the running process, so restarting the app clears every lockout. That restart is the manual unlock path.


# Where credentials are stored

Accounts are stored as salted `PBKDF2` hashes in `credentials.json`, in the app's data directory (`~/.local/share/splam/` by default).

Set `SPLAM_DATA_DIR` to relocate that directory:

- `/var/lib/splam` is the conventional choice for a system deployment
  - or `SPLAM_CREDENTIALS` to point at this one file.

The directory is created mode `0700` and the file mode `0600`, so it is readable only by the account running the app (i.e., treat it like `/etc/shadow`).
